Use "tvb_get_ntohieee_float()" to fetch floating-point numbers.
[obnox/wireshark/wip.git] / packet-ucp.c
index d99f6a161c5fb7ebf8b0ce20b5132952bfb0cef1..30390af2b4dc2e6fd9d2058f41e0e09dcbdf74c0 100644 (file)
@@ -2,7 +2,7 @@
  * Routines for Universal Computer Protocol dissection
  * Copyright 2001, Tom Uijldert <tom.uijldert@cmg.nl>
  *
- * $Id: packet-ucp.c,v 1.2 2001/10/08 17:37:52 guy Exp $
+ * $Id: packet-ucp.c,v 1.15 2002/04/11 09:10:47 guy Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 # include "snprintf.h"
 #endif
 
-#include "packet.h"
+#include <epan/packet.h>
 /* #include "packet-ucp.h" */                  /* We autoregister      */
 
+/* Prototypes  */
+static void dissect_ucp(tvbuff_t *, packet_info *, proto_tree *);
+
 /*
  * Convert ASCII-hex character to binary equivalent. No checks, assume
  * is valid hex character.
@@ -196,6 +199,7 @@ static int hf_xser_service  = -1;
 
 /* Initialize the subtree pointers */
 static gint ett_ucp  = -1;
+static gint ett_sub  = -1;
 static gint ett_XSer = -1;
 
 /*
@@ -625,10 +629,6 @@ static const value_string vals_xser_service[] = {
  * \retval     UCP_SHORTENED   Packet may be there, but not complete
  * \retval     UCP_MALFORMED   Hmmmm, not UCP after all...
  * \retval     UCP_INV_CHK     Nice packet, but checksum doesn't add up...
- *
- * Note that this will not recognize any frames as UCP frames if the
- * capture was made with a snapshot length shorter than the maximum
- * frame length, as it checksums the entire packet.
  */
 static int
 check_ucp(tvbuff_t *tvb, int *endpkt)
@@ -638,9 +638,6 @@ check_ucp(tvbuff_t *tvb, int *endpkt)
     int                 pkt_check, tmp;
     int                 length;
 
-    if (!tvb_offset_exists(tvb, 0) || tvb_get_guint8(tvb, 0) != UCP_STX)
-       return UCP_MALFORMED;
-
     length = tvb_find_guint8(tvb, offset, -1, UCP_ETX);
     if (length == -1) {
        *endpkt = tvb_reported_length_remaining(tvb, offset);
@@ -677,17 +674,20 @@ ucp_mktime(char *datestr)
     struct tm   r_time;
 
     r_time.tm_mday = 10 * (datestr[0] - '0') + (datestr[1] - '0');
-    r_time.tm_mon  = 10 * (datestr[2] - '0') + (datestr[3] - '0');
+    r_time.tm_mon  = (10 * (datestr[2] - '0') + (datestr[3] - '0')) - 1;
     r_time.tm_year = 10 * (datestr[4] - '0') + (datestr[5] - '0');
+    if (r_time.tm_year < 90) 
+       r_time.tm_year += 100;
     r_time.tm_hour = 10 * (datestr[6] - '0') + (datestr[7] - '0');
     r_time.tm_min  = 10 * (datestr[8] - '0') + (datestr[9] - '0');
     if (datestr[10])
        r_time.tm_sec  = 10 * (datestr[10] - '0') + (datestr[11] - '0');
+    r_time.tm_isdst = -1;
     return mktime(&r_time);
 }
 
 /*!
- * Scanning rouines to add standard types (byte, int, string, data)
+ * Scanning routines to add standard types (byte, int, string, data)
  * to the protocol-tree. Each field is seperated with a slash ('/').
  *
  * \param      tree    The protocol tree to add to
@@ -1453,7 +1453,9 @@ add_5xO(proto_tree *tree, tvbuff_t *tvb)
     UcpHandleByte(hf_ucp_parm_Dst);
     UcpHandleInt(hf_ucp_parm_Rsn);
     UcpHandleTime(hf_ucp_parm_DSCTS);
-    ucp_handle_mt(tree, tvb, &offset);
+    UcpHandleByte(hf_ucp_parm_MT);
+    UcpHandleString(hf_ucp_parm_NB);
+    UcpHandleData(hf_ucp_data_section);
     UcpHandleByte(hf_ucp_parm_MMS);
     UcpHandleByte(hf_ucp_parm_PR);
     UcpHandleByte(hf_ucp_parm_DCs);
@@ -1525,22 +1527,23 @@ add_6xO(proto_tree *tree, tvbuff_t *tvb, guint8 OT)
 #undef UcpHandleData
 
 /* Code to actually dissect the packets */
+/*
+ * Overlapping data for these functions
+ */
+static int      result, endpkt;
+
+/*
+ * The heuristic dissector
+ */
 static gboolean
-dissect_ucp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_ucp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-    int                 offset = 0;    /* Offset in packet within tvbuff       */
-    int                 tmpoff;        /* Local offset value (per field)       */
     guint8      O_R;           /* Request or response                  */
-    guint8      OT;            /* Operation type                       */
-    guint       intval;
-    int                 result, endpkt;
-    int                 i;
 
-    /* Set up structures needed to add the protocol subtree and manage it */
-    proto_item *ti;
-    proto_item *sub_ti;
-    proto_tree *ucp_tree;
-    tvbuff_t   *tmp_tvb;
+    /* This runs atop TCP, so we are guaranteed that there is at least one
+       byte in the tvbuff. */
+    if (tvb_get_guint8(tvb, 0) != UCP_STX)
+       return FALSE;
 
     result = check_ucp(tvb, &endpkt);
 
@@ -1558,6 +1561,34 @@ dissect_ucp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     O_R = tvb_get_guint8(tvb, UCP_O_R_OFFSET);
     if (match_strval(O_R, vals_hdr_O_R) == NULL)
        return FALSE;
+    /*
+     * Ok, looks like a valid packet, go dissect.
+     */
+    dissect_ucp(tvb, pinfo, tree);
+    return TRUE;
+}
+
+/*
+ * The actual dissector
+ */
+static void
+dissect_ucp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+    int                 offset = 0;    /* Offset in packet within tvbuff       */
+    int                 tmpoff;        /* Local offset value (per field)       */
+    guint8      O_R;           /* Request or response                  */
+    guint8      OT;            /* Operation type                       */
+    guint       intval;
+    int                 i;
+
+    /* Set up structures needed to add the protocol subtree and manage it */
+    proto_item *ti;
+    proto_item *sub_ti;
+    proto_tree *ucp_tree;
+    proto_tree *sub_tree;
+    tvbuff_t   *tmp_tvb;
+
+    O_R = tvb_get_guint8(tvb, UCP_O_R_OFFSET);
     /*
      * So do an atoi() on the operation type
      */
@@ -1565,18 +1596,18 @@ dissect_ucp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     OT  = 10 * OT + (tvb_get_guint8(tvb, UCP_OT_OFFSET + 1) - '0');
 
     /* Make entries in Protocol column and Info column on summary display */
-    if (check_col(pinfo->fd, COL_PROTOCOL))
-           col_set_str(pinfo->fd, COL_PROTOCOL, "UCP");
+    if (check_col(pinfo->cinfo, COL_PROTOCOL))
+           col_set_str(pinfo->cinfo, COL_PROTOCOL, "UCP");
 
-    if (check_col(pinfo->fd, COL_INFO)) {
-       col_clear(pinfo->fd, COL_INFO);
-       col_append_fstr(pinfo->fd, COL_INFO, "%s (%s)",
+    if (check_col(pinfo->cinfo, COL_INFO)) {
+       col_clear(pinfo->cinfo, COL_INFO);
+       col_append_fstr(pinfo->cinfo, COL_INFO, "%s (%s)",
                     val_to_str(OT,  vals_hdr_OT,  "unknown operation"),
                     match_strval(O_R, vals_hdr_O_R));
        if (result == UCP_SHORTENED)
-           col_append_str(pinfo->fd, COL_INFO, " [short packet]");
+           col_append_str(pinfo->cinfo, COL_INFO, " [short packet]");
        else if (result == UCP_INV_CHK)
-           col_append_str(pinfo->fd, COL_INFO, " [checksum invalid]");
+           col_append_str(pinfo->cinfo, COL_INFO, " [checksum invalid]");
     }
 
     /* In the interest of speed, if "tree" is NULL, don't do any work not
@@ -1584,8 +1615,7 @@ dissect_ucp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     if (tree) {
 
        /* create display subtree for the protocol */
-       ti = proto_tree_add_item(tree, proto_ucp, tvb, 0,
-                                tvb_length(tvb), FALSE);
+       ti = proto_tree_add_item(tree, proto_ucp, tvb, 0, -1, FALSE);
 
        ucp_tree = proto_item_add_subtree(ti, ett_ucp);
        /*
@@ -1623,102 +1653,103 @@ dissect_ucp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
         * Variable part starts here. Don't dissect if not complete.
         */
        if (result == UCP_SHORTENED)
-           return TRUE;
+           return;
        tmp_tvb = tvb_new_subset(tvb, offset, -1, -1);
        sub_ti = proto_tree_add_item(ucp_tree, hf_ucp_oper_section, tvb,
                                     offset, endpkt - offset, FALSE);
+       sub_tree = proto_item_add_subtree(sub_ti, ett_sub);
 
        switch (OT) {
            case  1:
-               O_R == 'O' ? add_01O(sub_ti,tmp_tvb) : add_01R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_01O(sub_tree,tmp_tvb) : add_01R(sub_tree,tmp_tvb);
                break;
            case  2:
-               O_R == 'O' ? add_02O(sub_ti,tmp_tvb) : add_02R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_02O(sub_tree,tmp_tvb) : add_02R(sub_tree,tmp_tvb);
                break;
            case  3:
-               O_R == 'O' ? add_03O(sub_ti,tmp_tvb) : add_03R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_03O(sub_tree,tmp_tvb) : add_03R(sub_tree,tmp_tvb);
                break;
            case  4:
-               O_R == 'O' ? add_04O(sub_ti,tmp_tvb) : add_04R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_04O(sub_tree,tmp_tvb) : add_04R(sub_tree,tmp_tvb);
                break;
            case  5:
-               O_R == 'O' ? add_05O(sub_ti,tmp_tvb) : add_05R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_05O(sub_tree,tmp_tvb) : add_05R(sub_tree,tmp_tvb);
                break;
            case  6:
-               O_R == 'O' ? add_06O(sub_ti,tmp_tvb) : add_06R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_06O(sub_tree,tmp_tvb) : add_06R(sub_tree,tmp_tvb);
                break;
            case  7:
-               O_R == 'O' ? add_07O(sub_ti,tmp_tvb) : add_07R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_07O(sub_tree,tmp_tvb) : add_07R(sub_tree,tmp_tvb);
                break;
            case  8:
-               O_R == 'O' ? add_08O(sub_ti,tmp_tvb) : add_08R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_08O(sub_tree,tmp_tvb) : add_08R(sub_tree,tmp_tvb);
                break;
            case  9:
-               O_R == 'O' ? add_09O(sub_ti,tmp_tvb) : add_09R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_09O(sub_tree,tmp_tvb) : add_09R(sub_tree,tmp_tvb);
                break;
            case 10:
-               O_R == 'O' ? add_10O(sub_ti,tmp_tvb) : add_10R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_10O(sub_tree,tmp_tvb) : add_10R(sub_tree,tmp_tvb);
                break;
            case 11:
-               O_R == 'O' ? add_11O(sub_ti,tmp_tvb) : add_11R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_11O(sub_tree,tmp_tvb) : add_11R(sub_tree,tmp_tvb);
                break;
            case 12:
-               O_R == 'O' ? add_12O(sub_ti,tmp_tvb) : add_12R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_12O(sub_tree,tmp_tvb) : add_12R(sub_tree,tmp_tvb);
                break;
            case 13:
-               O_R == 'O' ? add_13O(sub_ti,tmp_tvb) : add_13R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_13O(sub_tree,tmp_tvb) : add_13R(sub_tree,tmp_tvb);
                break;
            case 14:
-               O_R == 'O' ? add_14O(sub_ti,tmp_tvb) : add_14R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_14O(sub_tree,tmp_tvb) : add_14R(sub_tree,tmp_tvb);
                break;
            case 15:
-               O_R == 'O' ? add_15O(sub_ti,tmp_tvb) : add_15R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_15O(sub_tree,tmp_tvb) : add_15R(sub_tree,tmp_tvb);
                break;
            case 16:
-               O_R == 'O' ? add_16O(sub_ti,tmp_tvb) : add_16R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_16O(sub_tree,tmp_tvb) : add_16R(sub_tree,tmp_tvb);
                break;
            case 17:
-               O_R == 'O' ? add_17O(sub_ti,tmp_tvb) : add_17R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_17O(sub_tree,tmp_tvb) : add_17R(sub_tree,tmp_tvb);
                break;
            case 18:
-               O_R == 'O' ? add_18O(sub_ti,tmp_tvb) : add_18R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_18O(sub_tree,tmp_tvb) : add_18R(sub_tree,tmp_tvb);
                break;
            case 19:
-               O_R == 'O' ? add_19O(sub_ti,tmp_tvb) : add_19R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_19O(sub_tree,tmp_tvb) : add_19R(sub_tree,tmp_tvb);
                break;
            case 20:
-               O_R == 'O' ? add_20O(sub_ti,tmp_tvb) : add_20R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_20O(sub_tree,tmp_tvb) : add_20R(sub_tree,tmp_tvb);
                break;
            case 21:
-               O_R == 'O' ? add_21O(sub_ti,tmp_tvb) : add_21R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_21O(sub_tree,tmp_tvb) : add_21R(sub_tree,tmp_tvb);
                break;
            case 22:
-               O_R == 'O' ? add_22O(sub_ti,tmp_tvb) : add_22R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_22O(sub_tree,tmp_tvb) : add_22R(sub_tree,tmp_tvb);
                break;
            case 23:
-               O_R == 'O' ? add_23O(sub_ti,tmp_tvb) : add_23R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_23O(sub_tree,tmp_tvb) : add_23R(sub_tree,tmp_tvb);
                break;
            case 24:
-               O_R == 'O' ? add_24O(sub_ti,tmp_tvb) : add_24R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_24O(sub_tree,tmp_tvb) : add_24R(sub_tree,tmp_tvb);
                break;
            case 30:
-               O_R == 'O' ? add_30O(sub_ti,tmp_tvb) : add_30R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_30O(sub_tree,tmp_tvb) : add_30R(sub_tree,tmp_tvb);
                break;
            case 31:
-               O_R == 'O' ? add_31O(sub_ti,tmp_tvb) : add_31R(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_31O(sub_tree,tmp_tvb) : add_31R(sub_tree,tmp_tvb);
                break;
            case 51: case 52: case 53: case 54: case 55: case 56: case 57:
            case 58:
-               O_R == 'O' ? add_5xO(sub_ti,tmp_tvb) : add_5xR(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_5xO(sub_tree,tmp_tvb) : add_5xR(sub_tree,tmp_tvb);
                break;
            case 60: case 61:
-               O_R == 'O' ? add_6xO(sub_ti,tmp_tvb,OT) : add_6xR(sub_ti,tmp_tvb);
+               O_R == 'O' ? add_6xO(sub_tree,tmp_tvb,OT) : add_6xR(sub_tree,tmp_tvb);
                break;
            default:
                break;
        }
     }
-    return TRUE;
+    return;
 }
 
 /* Register the protocol with Ethereal */
@@ -2073,7 +2104,7 @@ proto_register_ucp(void)
        },
        { &hf_ucp_parm_NT,
            { "NT", "ucp.parm.NT",
-             FT_STRING, BASE_NONE, NULL, 0x00,
+             FT_UINT8, BASE_DEC, VALS(vals_parm_NT), 0x00,
              "Notification type.",
              HFILL
            }
@@ -2453,6 +2484,7 @@ proto_register_ucp(void)
     /* Setup protocol subtree array */
     static gint *ett[] = {
        &ett_ucp,
+       &ett_sub,
        &ett_XSer
     };
     /* Register the protocol name and description */
@@ -2472,9 +2504,17 @@ proto_register_ucp(void)
 void
 proto_reg_handoff_ucp(void)
 {
+    dissector_handle_t ucp_handle;
+
     /*
      * UCP can be spoken on any port so, when not on a specific port, try this
      * one whenever TCP is spoken.
      */
-    heur_dissector_add("tcp", dissect_ucp, proto_ucp);
+    heur_dissector_add("tcp", dissect_ucp_heur, proto_ucp);
+
+    /*
+     * Also register as one that can be selected by a TCP port number.
+     */
+    ucp_handle = create_dissector_handle(dissect_ucp, proto_ucp);
+    dissector_add_handle("tcp.port", ucp_handle);
 }