From Didier Gautheron:
[obnox/wireshark/wip.git] / plugins / profinet / packet-pn-mrp.c
index 0d56a4a08a0951a68bcefbcbc7732ecda3bcc3ba..48d25a283299d5e2983d6323da74e742c7d892e6 100644 (file)
@@ -4,8 +4,8 @@
  *
  * $Id$
  *
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * 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
@@ -40,6 +40,9 @@
 #include <epan/oui.h>
 #include <epan/etypes.h>
 
+#include "packet-pn.h"
+
+
 static int proto_pn_mrp = -1;
 
 static int hf_pn_mrp_type = -1;
@@ -56,8 +59,7 @@ static int hf_pn_mrp_time_stamp = -1;
 static int hf_pn_mrp_blocked = -1;
 static int hf_pn_mrp_manufacturer_oui = -1;
 static int hf_pn_mrp_domain_uuid = -1;
-
-static int hf_pn_mrp_data = -1;
+static int hf_pn_mrp_oui = -1;
 
 
 static gint ett_pn_mrp = -1;
@@ -78,6 +80,7 @@ static const value_string pn_mrp_block_type_vals[] = {
 
 static const value_string pn_mrp_oui_vals[] = {
        { OUI_PROFINET,         "PROFINET" },
+       { OUI_SIEMENS,          "SIEMENS" },
 
        { 0, NULL }
 };
@@ -109,33 +112,9 @@ static const value_string pn_mrp_prio_vals[] = {
 
 
 
-/* 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);
-
-extern int dissect_pn_int16(tvbuff_t *tvb, gint offset, packet_info *pinfo _U_,
-                       proto_tree *tree, int hfindex, gint16 *pdata);
-
-extern int dissect_pn_oid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
-                    proto_tree *tree, int hfindex, guint32 *pdata);
-
-extern int dissect_pn_mac(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
-                    proto_tree *tree, int hfindex, guint8 *pdata);
-
-extern int dissect_pn_uuid(tvbuff_t *tvb, int offset, packet_info *pinfo _U_,
-                    proto_tree *tree, int hfindex, e_uuid_t *uuid);
-
-
-
 static int
 dissect_PNMRP_Common(tvbuff_t *tvb, int offset, 
-       packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 length)
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
 {
     guint16 sequence_id;
     e_uuid_t uuid;
@@ -147,8 +126,7 @@ dissect_PNMRP_Common(tvbuff_t *tvb, int offset,
     /* MRP_DomainUUID */
     offset = dissect_pn_uuid(tvb, offset, pinfo, tree, hf_pn_mrp_domain_uuid, &uuid);
 
-    if (check_col(pinfo->cinfo, COL_INFO))
-      col_append_fstr(pinfo->cinfo, COL_INFO, "Common");
+    col_append_str(pinfo->cinfo, COL_INFO, "Common");
 
     proto_item_append_text(item, "Common");
 
@@ -158,7 +136,7 @@ dissect_PNMRP_Common(tvbuff_t *tvb, int offset,
 
 static int
 dissect_PNMRP_LinkUp(tvbuff_t *tvb, int offset, 
-       packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 length)
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
 {
     guint16 port_role;
     guint16 interval;
@@ -175,12 +153,9 @@ dissect_PNMRP_LinkUp(tvbuff_t *tvb, int offset,
     offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_blocked, &blocked);
 
     /* Padding */
-    if (offset % 4) {
-        offset += 4 - (offset % 4);
-    }
+    offset = dissect_pn_align4(tvb, offset, pinfo, tree);
 
-    if (check_col(pinfo->cinfo, COL_INFO))
-      col_append_fstr(pinfo->cinfo, COL_INFO, "LinkUp");
+    col_append_str(pinfo->cinfo, COL_INFO, "LinkUp");
 
     proto_item_append_text(item, "LinkUp");
 
@@ -190,7 +165,7 @@ dissect_PNMRP_LinkUp(tvbuff_t *tvb, int offset,
 
 static int
 dissect_PNMRP_LinkDown(tvbuff_t *tvb, int offset, 
-       packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 length)
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
 {
     guint16 port_role;
     guint16 interval;
@@ -207,12 +182,9 @@ dissect_PNMRP_LinkDown(tvbuff_t *tvb, int offset,
     offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_blocked, &blocked);
 
     /* Padding */
-    if (offset % 4) {
-        offset += 4 - (offset % 4);
-    }
+    offset = dissect_pn_align4(tvb, offset, pinfo, tree);
 
-    if (check_col(pinfo->cinfo, COL_INFO))
-      col_append_fstr(pinfo->cinfo, COL_INFO, "LinkDown");
+    col_append_str(pinfo->cinfo, COL_INFO, "LinkDown");
 
     proto_item_append_text(item, "LinkDown");
 
@@ -222,7 +194,7 @@ dissect_PNMRP_LinkDown(tvbuff_t *tvb, int offset,
 
 static int
 dissect_PNMRP_Test(tvbuff_t *tvb, int offset, 
-       packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 length)
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
 {
     guint16 prio;
     guint8 mac[6];
@@ -251,12 +223,9 @@ dissect_PNMRP_Test(tvbuff_t *tvb, int offset,
     offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_time_stamp, &time_stamp);
 
     /* Padding */
-    if (offset % 4) {
-        offset += 4 - (offset % 4);
-    }
+    offset = dissect_pn_align4(tvb, offset, pinfo, tree);
 
-    if (check_col(pinfo->cinfo, COL_INFO))
-      col_append_fstr(pinfo->cinfo, COL_INFO, "Test");
+    col_append_str(pinfo->cinfo, COL_INFO, "Test");
 
     proto_item_append_text(item, "Test");
 
@@ -266,7 +235,7 @@ dissect_PNMRP_Test(tvbuff_t *tvb, int offset,
 
 static int
 dissect_PNMRP_TopologyChange(tvbuff_t *tvb, int offset, 
-       packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 length)
+       packet_info *pinfo, proto_tree *tree, proto_item *item)
 {
     guint16 prio;
     guint8 mac[6];
@@ -283,12 +252,9 @@ dissect_PNMRP_TopologyChange(tvbuff_t *tvb, int offset,
     offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_interval, &interval);
 
     /* Padding */
-    /*if (offset % 4) {
-        offset += 4 - (offset % 4);
-    }*/
+    /*offset = dissect_pn_align4(tvb, offset, pinfo, tree);*/
 
-    if (check_col(pinfo->cinfo, COL_INFO))
-      col_append_fstr(pinfo->cinfo, COL_INFO, "TopologyChange");
+    col_append_str(pinfo->cinfo, COL_INFO, "TopologyChange");
 
     proto_item_append_text(item, "TopologyChange");
 
@@ -296,6 +262,47 @@ dissect_PNMRP_TopologyChange(tvbuff_t *tvb, int offset,
 }
 
 
+static int
+dissect_PNMRP_Option(tvbuff_t *tvb, int offset, 
+       packet_info *pinfo, proto_tree *tree, proto_item *item, guint8 length)
+{
+    guint32 oui;
+
+
+    /* OUI (organizational unique id) */
+    offset = dissect_pn_oid(tvb, offset, pinfo,tree, hf_pn_mrp_oui, &oui);
+    length -= 3;
+       
+    switch (oui)
+       {
+       case OUI_SIEMENS:
+        proto_item_append_text(item, "Option(SIEMENS)");
+        /* Padding */
+        if (offset % 4) {
+            length -= 4 - (offset % 4);
+            offset = dissect_pn_align4(tvb, offset, pinfo, tree);
+        }
+        if(length != 0) {
+            offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length);
+        }
+        col_append_str(pinfo->cinfo, COL_INFO, "Option(Siemens)");
+               break;
+       default:
+        proto_item_append_text(item, "Option(Unknown-OUI)");
+        offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length);
+
+        col_append_str(pinfo->cinfo, COL_INFO, "Option");
+    }
+
+    offset += length;
+
+    /* Padding */
+    offset = dissect_pn_align4(tvb, offset, pinfo, tree);
+
+    return offset;
+}
+
+
 static int
 dissect_PNMRP_PDU(tvbuff_t *tvb, int offset, 
        packet_info *pinfo, proto_tree *tree, proto_item *item)
@@ -303,64 +310,65 @@ dissect_PNMRP_PDU(tvbuff_t *tvb, int offset,
     guint16 version;
     guint8 type;
     guint8 length;
-    gint i = 0;
+    gint i;
+    tvbuff_t *tvb_new;
 
 
     /* MRP_Version */
     offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_version, &version);
 
-    while(tvb_length_remaining(tvb, offset) > 0) {
+    /* the rest of the packet has 4byte alignment regarding to the beginning of the next TLV block! */
+    /* XXX - do we have to free this new tvb below? */
+    tvb_new = tvb_new_subset_remaining(tvb, offset);
+    offset = 0;
+
+    for(i=0; tvb_length_remaining(tvb, offset) > 0; i++) {
         /* MRP_TLVHeader.Type */
-        offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_mrp_type, &type);
+        offset = dissect_pn_uint8(tvb_new, offset, pinfo, tree, hf_pn_mrp_type, &type);
 
         /* MRP_TLVHeader.Length */
-        offset = dissect_pn_uint8(tvb, offset, pinfo, tree, hf_pn_mrp_length, &length);
+        offset = dissect_pn_uint8(tvb_new, offset, pinfo, tree, hf_pn_mrp_length, &length);
 
         if(i != 0) {
-            if (check_col(pinfo->cinfo, COL_INFO))
-              col_append_fstr(pinfo->cinfo, COL_INFO, ", ");
+            col_append_str(pinfo->cinfo, COL_INFO, ", ");
 
             proto_item_append_text(item, ", ");
         }
 
-        i++;
-
         switch(type) {
         case(0x00):
             /* no content */
-            if (check_col(pinfo->cinfo, COL_INFO))
-              col_append_fstr(pinfo->cinfo, COL_INFO, "End");
+            col_append_str(pinfo->cinfo, COL_INFO, "End");
             proto_item_append_text(item, "End");
             return offset;
             break;
         case(0x01):
-            offset = dissect_PNMRP_Common(tvb, offset, pinfo, tree, item, length);
+            offset = dissect_PNMRP_Common(tvb_new, offset, pinfo, tree, item);
             break;
         case(0x02):
-            offset = dissect_PNMRP_Test(tvb, offset, pinfo, tree, item, length);
+            offset = dissect_PNMRP_Test(tvb_new, offset, pinfo, tree, item);
             break;
         case(0x03):
-            offset = dissect_PNMRP_TopologyChange(tvb, offset, pinfo, tree, item, length);
+            offset = dissect_PNMRP_TopologyChange(tvb_new, offset, pinfo, tree, item);
             break;
         case(0x04):
-            offset = dissect_PNMRP_LinkDown(tvb, offset, pinfo, tree, item, length);
+            offset = dissect_PNMRP_LinkDown(tvb_new, offset, pinfo, tree, item);
             break;
         case(0x05):
-            offset = dissect_PNMRP_LinkUp(tvb, offset, pinfo, tree, item, length);
+            offset = dissect_PNMRP_LinkUp(tvb_new, offset, pinfo, tree, item);
+            break;
+        case(0x7f):
+            offset = dissect_PNMRP_Option(tvb_new, offset, pinfo, tree, item, length);
             break;
         default:
-            proto_tree_add_string_format(tree, hf_pn_mrp_data, tvb, offset, length, "data", 
-                "PN-MRP Unknown TLVType 0x%x, Data: %d bytes", type, length);
-               if (check_col(pinfo->cinfo, COL_INFO))
-                       col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TLVType 0x%x", type);
-
-               proto_item_append_text(item, "Unknown TLVType 0x%x", type);
+            offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length);
 
-            offset += length;
+            if (check_col(pinfo->cinfo, COL_INFO))
+                   col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TLVType 0x%x", type);
+           proto_item_append_text(item, "Unknown TLVType 0x%x", type);
         }
     }
 
-    /* will never be reached */
     return offset;
 }
 
@@ -369,24 +377,21 @@ dissect_PNMRP_PDU(tvbuff_t *tvb, int offset,
 static void
 dissect_PNMRP(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-       proto_item *ti;
-       proto_tree *mrp_tree = NULL;
+    proto_item *ti = NULL;
+    proto_tree *mrp_tree = NULL;
        
-       guint32 offset = 0;
+    guint32 offset = 0;
 
-       if (check_col(pinfo->cinfo, COL_PROTOCOL)) 
-               col_set_str(pinfo->cinfo, COL_PROTOCOL, "PN-MRP");
+    col_set_str(pinfo->cinfo, COL_PROTOCOL, "PN-MRP");
                
-       /* Clear the information column on summary display */
-       if (check_col(pinfo->cinfo, COL_INFO)) {
-                       col_clear(pinfo->cinfo, COL_INFO);
-       }
+    /* Clear the information column on summary display */
+    col_clear(pinfo->cinfo, COL_INFO);
 
-       if (tree) 
-       {
-               ti = proto_tree_add_item(tree, proto_pn_mrp, tvb, offset, -1, FALSE);
-               mrp_tree = proto_item_add_subtree(ti, ett_pn_mrp);
-       }
+    if (tree) 
+    {
+        ti = proto_tree_add_item(tree, proto_pn_mrp, tvb, offset, -1, FALSE);
+        mrp_tree = proto_item_add_subtree(ti, ett_pn_mrp);
+    }
 
     dissect_PNMRP_PDU(tvb, offset, pinfo, mrp_tree, ti);
 }      
@@ -396,25 +401,22 @@ void
 proto_register_pn_mrp (void)
 {
        static hf_register_info hf[] = {
-    { &hf_pn_mrp_data,
-        { "Undecoded Data", "pn_mrp.data", FT_STRING, BASE_DEC, NULL, 0x0, "", HFILL }},
-
        { &hf_pn_mrp_type,
-               { "Type", "pn_mrp.type", FT_UINT8, BASE_HEX, VALS(pn_mrp_block_type_vals), 0x0, "", HFILL }},
+               { "Type", "pn_mrp.type", FT_UINT8, BASE_HEX, VALS(pn_mrp_block_type_vals), 0x0, NULL, HFILL }},
        { &hf_pn_mrp_length,
-               { "Length", "pn_mrp.length", FT_UINT8, BASE_DEC, NULL, 0x0, "", HFILL }},
+               { "Length", "pn_mrp.length", FT_UINT8, BASE_DEC, NULL, 0x0, NULL, HFILL }},
        { &hf_pn_mrp_version,
-               { "Version", "pn_mrp.version", FT_UINT16, BASE_DEC, NULL, 0x0, "", HFILL }},
+               { "Version", "pn_mrp.version", FT_UINT16, BASE_DEC, NULL, 0x0, NULL, HFILL }},
        { &hf_pn_mrp_sequence_id,
                { "SequenceID", "pn_mrp.sequence_id", FT_UINT16, BASE_HEX, NULL, 0x0, "Unique sequence number to each outstanding service request", HFILL }},
        { &hf_pn_mrp_sa,
-        { "SA", "pn_mrp.sa", FT_ETHER, BASE_HEX, 0x0, 0x0, "", HFILL }},
+        { "SA", "pn_mrp.sa", FT_ETHER, BASE_NONE, 0x0, 0x0, NULL, HFILL }},
        { &hf_pn_mrp_prio,
-               { "Prio", "pn_mrp.prio", FT_UINT16, BASE_HEX, VALS(pn_mrp_prio_vals), 0x0, "", HFILL }},
+               { "Prio", "pn_mrp.prio", FT_UINT16, BASE_HEX, VALS(pn_mrp_prio_vals), 0x0, NULL, HFILL }},
        { &hf_pn_mrp_port_role,
-               { "PortRole", "pn_mrp.port_role", FT_UINT16, BASE_HEX, VALS(pn_mrp_port_role_vals), 0x0, "", HFILL }},
+               { "PortRole", "pn_mrp.port_role", FT_UINT16, BASE_HEX, VALS(pn_mrp_port_role_vals), 0x0, NULL, HFILL }},
        { &hf_pn_mrp_ring_state,
-               { "RingState", "pn_mrp.ring_state", FT_UINT16, BASE_HEX, VALS(pn_mrp_ring_state_vals), 0x0, "", HFILL }},
+               { "RingState", "pn_mrp.ring_state", FT_UINT16, BASE_HEX, VALS(pn_mrp_ring_state_vals), 0x0, NULL, HFILL }},
        { &hf_pn_mrp_interval,
                { "Interval", "pn_mrp.interval", FT_UINT16, BASE_DEC, NULL, 0x0, "Interval for next topologie change event (in ms)", HFILL }},
        { &hf_pn_mrp_transition,
@@ -422,11 +424,14 @@ proto_register_pn_mrp (void)
        { &hf_pn_mrp_time_stamp,
                { "TimeStamp", "pn_mrp.time_stamp", FT_UINT16, BASE_HEX, NULL, 0x0, "Actual counter value of 1ms counter", HFILL }},
        { &hf_pn_mrp_blocked,
-               { "Blocked", "pn_mrp.blocked", FT_UINT16, BASE_HEX, NULL, 0x0, "", HFILL }},
+               { "Blocked", "pn_mrp.blocked", FT_UINT16, BASE_HEX, NULL, 0x0, NULL, HFILL }},
        { &hf_pn_mrp_manufacturer_oui,
-               { "ManufacturerOUI", "pn_mrp.manufacturer_oui", FT_UINT24, BASE_HEX, VALS(pn_mrp_oui_vals), 0x0, "", HFILL }},
+               { "ManufacturerOUI", "pn_mrp.manufacturer_oui", FT_UINT24, BASE_HEX, VALS(pn_mrp_oui_vals), 0x0, NULL, HFILL }},
        { &hf_pn_mrp_domain_uuid,
-               { "DomainUUID", "pn_mrp.domain_uuid", FT_GUID, BASE_NONE, NULL, 0x0, "", HFILL }},
+               { "DomainUUID", "pn_mrp.domain_uuid", FT_GUID, BASE_NONE, NULL, 0x0, NULL, HFILL }},
+       { &hf_pn_mrp_oui,
+               { "Organizationally Unique Identifier", "pn_mrp.oui", FT_UINT24, BASE_HEX,
+               VALS(pn_mrp_oui_vals), 0x0, NULL, HFILL }},
     };
 
        static gint *ett[] = {