Wireshark-dev: [Wireshark-dev] DCT2000 [Patch]
From: Martin Mathieson <[email protected]>
Date: Fri, 30 Jun 2006 17:29:03 +0100
Hi, this patch:

- Removes last traces of 'board ports only' preference
- Add a preference to try to find messages within sctp primitive messages (tries renaming of known mismatches)
- Add outhdr to stub protocol (getting ready for IuB FP)

Regards,
Martin
Index: wiretap/catapult_dct2000.c
===================================================================
--- wiretap/catapult_dct2000.c	(revision 18621)
+++ wiretap/catapult_dct2000.c	(working copy)
@@ -43,6 +43,7 @@
 #define MAX_PROTOCOL_NAME          64
 #define MAX_PORT_DIGITS            2
 #define MAX_VARIANT_DIGITS         32
+#define MAX_OUTHDR_NAME            64
 #define AAL_HEADER_CHARS           12
 
 /* TODO:
@@ -105,14 +106,9 @@
 /* The DCT2000 protocol name of the packet, plus variant number */
 static gchar protocol_name[MAX_PROTOCOL_NAME+1];
 static gchar variant_name[MAX_VARIANT_DIGITS+1];
+static gchar outhdr_name[MAX_OUTHDR_NAME+1];
 
 
-/*************************************************/
-/* Preference state (shared with stub protocol). */
-/* Set to FALSE to get better use out of other   */
-/* wiretap applications (mergecap, editcap)      */
-gboolean catapult_dct2000_board_ports_only = FALSE;
-
 /************************************************************/
 /* Functions called from wiretap                            */
 static gboolean catapult_dct2000_read(wtap *wth, int *err, gchar **err_info,
@@ -137,8 +133,7 @@
                            long *data_offset,
                            gint *data_chars,
                            packet_direction_t *direction,
-                           int *encap,
-                           gboolean seek_read);
+                           int *encap);
 static int write_stub_header(guchar *frame_buffer, char *timestamp_string,
                       packet_direction_t direction, int encap);
 static guchar hex_from_char(gchar c);
@@ -319,7 +314,7 @@
         if (parse_line(line_length, &seconds, &useconds,
                        &before_time_offset, &after_time_offset,
                        &dollar_offset,
-                       &data_chars, &direction, &encap, FALSE))
+                       &data_chars, &direction, &encap))
         {
             guchar *frame_buffer;
             int n;
@@ -444,7 +439,7 @@
     if (parse_line(length, &seconds, &useconds,
                    &before_time_offset, &after_time_offset,
                    &dollar_offset,
-                   &data_chars, &direction, &encap, TRUE))
+                   &data_chars, &direction, &encap))
     {
         int n;
         int stub_offset = 0;
@@ -652,6 +647,10 @@
     for (; pd[n] != '\0'; n++);
     n++;
 
+    /* Outhdr (as string) */
+    for (; pd[n] != '\0'; n++);
+    n++;
+
     /* Direction & encap */
     n += 2;
 
@@ -737,14 +736,15 @@
                     long *before_time_offset, long *after_time_offset,
                     long *data_offset, gint *data_chars,
                     packet_direction_t *direction,
-                    int *encap,
-                    gboolean seek_read)
+                    int *encap)
 {
     int  n = 0;
     int  port_digits = 0;
     char port_number_string[MAX_PORT_DIGITS+1];
     int  variant_digits = 0;
+    int  variant = 1;
     int  protocol_chars = 0;
+    int  outhdr_chars = 0;
 
     char seconds_buff[MAX_SECONDS_CHARS+1];
     int  seconds_chars;
@@ -831,6 +831,61 @@
     n++;
 
 
+    /* Following the / is the variant number.  No digits indicate 1 */
+    for (variant_digits = 0;
+         (isdigit(linebuff[n])) && (variant_digits <= MAX_VARIANT_DIGITS) && (n+1 < line_length);
+         n++, variant_digits++)
+    {
+        if (!isdigit(linebuff[n]))
+        {
+            return FALSE;
+        }
+        variant_name[variant_digits] = linebuff[n];
+    }
+    if (variant_digits > MAX_VARIANT_DIGITS || (n+1 >= line_length))
+    {
+        return FALSE;
+    }
+    if (variant_digits > 0)
+    {
+        variant_name[variant_digits] = '\0';
+        variant = atoi(variant_name);
+    }
+    else
+    {
+        strcpy(variant_name, "1");
+    }
+
+
+    /* Outheader values may follow */
+    outhdr_name[0] = '\0';
+    if (linebuff[n] == ',')
+    {
+        /* Skip , */
+        n++;
+
+        for (outhdr_chars = 0;
+             (isdigit(linebuff[n]) || linebuff[n] == ',') &&
+             (outhdr_chars <= MAX_OUTHDR_NAME) && (n+1 < line_length);
+             n++, outhdr_chars++)
+        {
+            if (!isdigit(linebuff[n]) && (linebuff[n] != ','))
+            {
+                return FALSE;
+            }
+            outhdr_name[outhdr_chars] = linebuff[n];
+        }
+        if (outhdr_chars > MAX_OUTHDR_NAME || (n+1 >= line_length))
+        {
+            return FALSE;
+        }
+        /* Terminate (possibly empty) string */
+        outhdr_name[outhdr_chars] = '\0';
+    }
+
+
+
+
     /******************************************************************/
     /* Now check whether we know how to use a packet of this protocol */
 
@@ -840,14 +895,23 @@
     }
     else
 
-    /* For ATM protocols, we need to read the separate atm headerparse */
+    /* FP may be carried over ATM, which has separate atm header to parse */
     if ((strcmp(protocol_name, "fp") == 0) ||
         (strcmp(protocol_name, "fp_r4") == 0) ||
         (strcmp(protocol_name, "fp_r5") == 0) ||
         (strcmp(protocol_name, "fp_r6") == 0))
     {
-        *encap = WTAP_ENCAP_ATM_PDUS_UNTRUNCATED;
-        atm_header_present = TRUE;
+        if ((variant > 256) && (variant % 256 == 3))
+        {
+            /* FP over udp is contained in IPPrim... */
+            *encap = 0;
+        }
+        else
+        {
+            /* FP over AAL0 or AAL2 */
+            *encap = WTAP_ENCAP_ATM_PDUS_UNTRUNCATED;
+            atm_header_present = TRUE;
+        }
     }
 
     else
@@ -884,48 +948,11 @@
     }
     else
     {
-        /* Only reject protocol if reading for the first time and preference
-           setting says board ports only.  This should not fail to read a
-           non board-port protocol on re-reading because the preference setting
-           has since changed...
-        */
-        if (catapult_dct2000_board_ports_only && !seek_read)
-        {
-            return FALSE;
-        }
-        else
-        {
-            /* Not a supported protocol/encap, but should show as raw data anyway */
-            *encap = DCT2000_ENCAP_UNHANDLED;
-        }
+        /* Not a supported board port protocol/encap, but can show as raw data anyway */
+        *encap = DCT2000_ENCAP_UNHANDLED;
     }
 
 
-    /* Following the / is the variant number.  No digits indicate 1 */
-    for (variant_digits = 0;
-         (isdigit(linebuff[n])) && (variant_digits <= MAX_VARIANT_DIGITS) && (n+1 < line_length);
-         n++, variant_digits++)
-    {
-        if (!isdigit(linebuff[n]))
-        {
-            return FALSE;
-        }
-        variant_name[variant_digits] = linebuff[n];
-    }
-    if (variant_digits > MAX_VARIANT_DIGITS || (n+1 >= line_length))
-    {
-        return FALSE;
-    }
-    if (variant_digits > 0)
-    {
-        variant_name[variant_digits] = '\0';
-    }
-    else
-    {
-        strcpy(variant_name, "1");
-    }
-
-
     /* Find separate ATM header if necessary */
     if (atm_header_present)
     {
@@ -1106,10 +1133,14 @@
     strcpy((char*)&frame_buffer[stub_offset], protocol_name);
     stub_offset += (strlen(protocol_name) + 1);
 
-    /* Protocol variant number */
+    /* Protocol variant number (as string) */
     strcpy((void*)&frame_buffer[stub_offset], variant_name);
     stub_offset += (strlen(variant_name) + 1);
 
+    /* Outhdr */
+    strcpy((char*)&frame_buffer[stub_offset], outhdr_name);
+    stub_offset += (strlen(outhdr_name) + 1);
+
     /* Direction */
     frame_buffer[stub_offset] = direction;
     stub_offset++;
@@ -1117,7 +1148,7 @@
     /* Encap */
     frame_buffer[stub_offset] = (guint8)encap;
     stub_offset++;
-    
+
     return stub_offset;
 }
 
Index: epan/dissectors/packet-catapult-dct2000.c
===================================================================
--- epan/dissectors/packet-catapult-dct2000.c	(revision 18621)
+++ epan/dissectors/packet-catapult-dct2000.c	(working copy)
@@ -42,19 +42,21 @@
 static int hf_catapult_dct2000_timestamp = -1;
 static int hf_catapult_dct2000_protocol = -1;
 static int hf_catapult_dct2000_variant = -1;
+static int hf_catapult_dct2000_outhdr = -1;
 static int hf_catapult_dct2000_direction = -1;
 static int hf_catapult_dct2000_encap = -1;
 static int hf_catapult_dct2000_unparsed_data = -1;
 
 /* Variables used for preferences */
 gboolean catapult_dct2000_try_ipprim_heuristic = TRUE;
+gboolean catapult_dct2000_try_sctpprim_heuristic = TRUE;
 
 /* Protocol subtree. */
 static int ett_catapult_dct2000 = -1;
 
 static const value_string direction_vals[] = {
-	{ 0,   "Sent" },
-	{ 1,   "Received" },
+    { 0,   "Sent" },
+    { 1,   "Received" },
     { 0,   NULL },
 };
 
@@ -122,6 +124,80 @@
     return FALSE;
 }
 
+
+
+/* Look for the protocol data within an sctpprim (variant 1 or 2...) packet.
+   Only set *data_offset if data field found. */
+static gboolean find_sctpprim_data_offset(tvbuff_t *tvb, int *data_offset)
+{
+    guint8 length;
+    int offset = *data_offset;
+
+    /* Get the sctpprim command code. */
+    guint8 tag = tvb_get_guint8(tvb, offset++);
+
+    /* Only accept UDP or TCP data request or indication */
+    switch (tag)
+    {
+        case 0x04:  /* data request */
+        case 0x62:  /* data indication */
+            break;
+        default:
+            return FALSE;
+    }
+
+    /* Length field. msb set indicates 2 bytes */
+    if (tvb_get_guint8(tvb, offset) & 0x80)
+    {
+        offset += 2;
+    }
+    else
+    {
+        offset++;
+    }
+
+    /* Skip any other TLC fields before reach payload */
+    while (tvb_length_remaining(tvb, offset) > 2)
+    {
+        /* Look at next tag */
+        tag = tvb_get_guint8(tvb, offset++);
+
+        /* Is this the data payload we're expecting? */
+        if (tag == 0x19)
+        {
+            *data_offset = offset;
+            return TRUE;
+        }
+        else
+        {
+            /* Read length in next byte */
+            length = tvb_get_guint8(tvb, offset++);
+            /* Skip the following value */
+            offset += length;
+        }
+    }
+
+    /* No data found... */
+    return FALSE;
+}
+
+
+/* Look up dissector by protocol name.  Fix up known name mis-matches. */
+dissector_handle_t look_for_dissector(char *protocol_name)
+{
+    /* Use know aliases... */
+    if (strcmp(protocol_name, "tbcp") == 0)
+    {
+        return find_dissector("rtcp");
+    }
+    else
+    {
+        /* Presume name matches exactly */
+        return find_dissector(protocol_name);
+    }
+}
+
+
 /*****************************************/
 /* Main dissection function.             */
 /*****************************************/
@@ -139,11 +215,13 @@
     gint        timestamp_length;
     gint        variant_start;
     gint        variant_length;
+    gint        outhdr_start;
+    gint        outhdr_length;
     guint8      direction;
     tvbuff_t    *next_tvb;
     int         encap;
     dissector_handle_t protocol_handle = 0;
-    dissector_handle_t heur_ipprim_protocol_handle = 0;
+    dissector_handle_t heur_protocol_handle = 0;
     int sub_dissector_result = 0;
 
     /* Protocol name */
@@ -196,6 +274,17 @@
                         offset, variant_length, FALSE);
     offset += variant_length;
 
+    /* Outhdr */
+    outhdr_start = offset;
+    outhdr_length = tvb_strsize(tvb, offset);
+    if (outhdr_length > 1)
+    {
+        proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_outhdr, tvb,
+                            offset, outhdr_length, FALSE);
+    }
+    offset += outhdr_length;
+
+
     /* Direction */
     direction = tvb_get_guint8(tvb, offset);
     proto_tree_add_item(dct2000_tree, hf_catapult_dct2000_direction, tvb,
@@ -269,15 +358,29 @@
             /* Try IP Prim heuristic if configured to */
             if (catapult_dct2000_try_ipprim_heuristic)
             {
-                heur_ipprim_protocol_handle =
-                        find_dissector(tvb_get_ephemeral_string(tvb, protocol_start,
+                heur_protocol_handle =
+                    look_for_dissector(tvb_get_ephemeral_string(tvb, protocol_start,
                                                                 protocol_length));
-                if ((heur_ipprim_protocol_handle != 0) &&
+                if ((heur_protocol_handle != 0) &&
                     find_ipprim_data_offset(tvb, &offset))
                 {
-                    protocol_handle = heur_ipprim_protocol_handle;
+                    protocol_handle = heur_protocol_handle;
                 }
             }
+
+            /* Try SCTP Prim heuristic if configured to */
+            if (!protocol_handle && catapult_dct2000_try_sctpprim_heuristic)
+            {
+                heur_protocol_handle =
+                    look_for_dissector(tvb_get_ephemeral_string(tvb, protocol_start,
+                                                                protocol_length));
+                if ((heur_protocol_handle != 0) &&
+                    find_sctpprim_data_offset(tvb, &offset))
+                {
+                    protocol_handle = heur_protocol_handle;
+                }
+            }
+
             break;
 
         default:
@@ -370,6 +473,12 @@
               "DCT2000 protocol variant", HFILL
             }
         },
+        { &hf_catapult_dct2000_outhdr,
+            { "Out-header",
+              "dct2000.outhdr", FT_STRING, BASE_NONE, NULL, 0x0,
+              "DCT2000 protocol outhdr", HFILL
+            }
+        },
         { &hf_catapult_dct2000_direction,
             { "Direction",
               "dct2000.direction", FT_UINT8, BASE_DEC, VALS(direction_vals), 0x0,
@@ -410,24 +519,26 @@
     catapult_dct2000_module = prefs_register_protocol(proto_catapult_dct2000,
                                                       proto_reg_handoff_catapult_dct2000);
 
-    /* Determines whether non-supported protocols should be shown anyway */
-/*    prefs_register_bool_preference(catapult_dct2000_module, "board_ports_only",
-                                   "Only show known 'board-port' protocols",
-                                   "Don't show other protocols, i.e. unknown board-port "
-                                   "protocols and non-standard primitives between "
-                                   "contexts on the same card.  The capture file "
-                                   "needs to be (re)-loaded before effect will be seen",
-                                   &catapult_dct2000_board_ports_only);*/
-
     /* Determines whether for not-handled protocols we should try to parse it if:
        - it looks like its embedded in an ipprim message, AND
        - the DCT2000 protocol name matches an wireshark dissector name */
     prefs_register_bool_preference(catapult_dct2000_module, "ipprim_heuristic",
                                    "Use IP Primitive heuristic",
                                    "If a payload looks like its embedded in an "
-                                   "IP primitive messages, and there is an wireshark "
+                                   "IP primitive message, and there is an wireshark "
                                    "dissector matching the DCT2000 protocol name, "
                                    "try parsing the payload using that dissector",
                                    &catapult_dct2000_try_ipprim_heuristic);
+
+    /* Determines whether for not-handled protocols we should try to parse it if:
+       - it looks like its embedded in an sctpprim message, AND
+       - the DCT2000 protocol name matches an wireshark dissector name */
+    prefs_register_bool_preference(catapult_dct2000_module, "sctpprim_heuristic",
+                                   "Use SCTP Primitive heuristic",
+                                   "If a payload looks like its embedded in an "
+                                   "SCTP primitive message, and there is an wireshark "
+                                   "dissector matching the DCT2000 protocol name, "
+                                   "try parsing the payload using that dissector",
+                                   &catapult_dct2000_try_sctpprim_heuristic);
 }