Set the svn:eol-style property on all text files to "native", so that
[obnox/wireshark/wip.git] / packet-ucp.c
index aa2f6b111358eed822ad29361283758efd69b166..6ff5490dd1fa18a77d4f8301e8b59a2e55891e55 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.14 2002/03/10 03:07:16 guy Exp $
+ * $Id$
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
 #include <ctype.h>
 #include <time.h>
 
-#ifdef HAVE_SYS_TYPES_H
-# include <sys/types.h>
-#endif
-
-#ifdef HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-
 #include <glib.h>
 
-#ifdef NEED_SNPRINTF_H
-# include "snprintf.h"
-#endif
-
 #include <epan/packet.h>
 /* #include "packet-ucp.h" */                  /* We autoregister      */
 
@@ -118,6 +106,7 @@ static int hf_ucp_parm_NoA  = -1;
 static int hf_ucp_parm_NoB     = -1;
 static int hf_ucp_parm_NAC     = -1;
 static int hf_ucp_parm_PNC     = -1;
+static int hf_ucp_parm_AMsg    = -1;
 static int hf_ucp_parm_LNo     = -1;
 static int hf_ucp_parm_LST     = -1;
 static int hf_ucp_parm_TNo     = -1;
@@ -199,6 +188,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;
 
 /*
@@ -639,10 +629,12 @@ check_ucp(tvbuff_t *tvb, int *endpkt)
 
     length = tvb_find_guint8(tvb, offset, -1, UCP_ETX);
     if (length == -1) {
+       /* XXX - should we have an option to request reassembly? */
        *endpkt = tvb_reported_length_remaining(tvb, offset);
        return UCP_SHORTENED;
     }
     if (length > (int) tvb_reported_length(tvb)) {
+       /* XXX - "cannot happen" */
        *endpkt = 0;
        return UCP_MALFORMED;
     }
@@ -675,12 +667,14 @@ ucp_mktime(char *datestr)
     r_time.tm_mday = 10 * (datestr[0] - '0') + (datestr[1] - '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) 
+    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');
+    else
+       r_time.tm_sec  = 0;
     r_time.tm_isdst = -1;
     return mktime(&r_time);
 }
@@ -700,17 +694,68 @@ ucp_mktime(char *datestr)
 static void
 ucp_handle_string(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
 {
-    char        strval[BUFSIZ];
+    gint        idx, len;
+
+    idx = tvb_find_guint8(tvb, *offset, -1, '/');
+    if (idx == -1) {
+       /* Force the appropriate exception to be thrown. */
+       len = tvb_length_remaining(tvb, *offset);
+       tvb_ensure_bytes_exist(tvb, *offset, len + 1);
+    } else
+       len = idx - *offset;
+    if (len > 0)
+       proto_tree_add_item(tree, field, tvb, *offset, len, FALSE);
+    *offset += len;
+    if (idx != -1)
+       *offset += 1;   /* skip terminating '/' */
+}
+
+static void
+ucp_handle_IRAstring(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
+{
+    char        strval[BUFSIZ + 1],
+                *p_dst = strval;
+    guint8       byte;
     int                 idx = 0;
-    int                 tmpoff = *offset;
+    int          tmpoff = *offset;
 
-    idx = 0;
-    while ((strval[idx++] = tvb_get_guint8(tvb, tmpoff++)) != '/')
-       ;
-    if (idx > 1) {
-       strval[--idx] = '\0';
-       proto_tree_add_string(tree, field, tvb, *offset, idx, strval);
+    while (((byte = tvb_get_guint8(tvb, tmpoff++)) != '/') &&
+           (idx < BUFSIZ))
+    {
+        if (byte >= '0' && byte <= '9')
+        {
+            *p_dst = (byte - '0') * 16;
+        }
+        else
+        {
+            *p_dst = (byte - 'A' + 10) * 16;
+        }
+        if ((byte = tvb_get_guint8(tvb, tmpoff++)) == '/')
+        {
+            break;
+        }
+        if (byte >= '0' && byte <= '9')
+        {
+            *p_dst++ += byte - '0';
+        }
+        else
+        {
+            *p_dst++ += byte - 'A' + 10;
+        }
+        idx++;
     }
+    strval[idx] = '\0';
+    if (idx == BUFSIZ)
+    {
+        /*
+         * Data clipped, eat rest of field
+         */
+        while ((tvb_get_guint8(tvb, tmpoff++)) != '/')
+            ;
+    }
+    if ((tmpoff - *offset) > 1)
+       proto_tree_add_string(tree, field, tvb, *offset,
+                             tmpoff - *offset - 1, strval);
     *offset = tmpoff;
 }
 
@@ -729,41 +774,55 @@ ucp_handle_byte(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
 static guint
 ucp_handle_int(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
 {
-    char        strval[BUFSIZ];
+    gint        idx, len;
+    char        *strval;
     guint       intval = 0;
-    int                 tmpoff = *offset;
-    int                 idx = 0;
-    while ((strval[idx++] = tvb_get_guint8(tvb, tmpoff++)) != '/')
-       ;
-    if (idx > 1) {
-       strval[--idx] = '\0';
+
+    idx = tvb_find_guint8(tvb, *offset, -1, '/');
+    if (idx == -1) {
+       /* Force the appropriate exception to be thrown. */
+       len = tvb_length_remaining(tvb, *offset);
+       tvb_ensure_bytes_exist(tvb, *offset, len + 1);
+    } else
+       len = idx - *offset;
+    strval = tvb_get_string(tvb, *offset, len);
+    if (len > 0) {
        intval = atoi(strval);
        proto_tree_add_uint(tree, field, tvb, *offset, idx, intval);
     }
-    *offset = tmpoff;
+    g_free(strval);
+    *offset += len;
+    if (idx != -1)
+       *offset += 1;   /* skip terminating '/' */
     return intval;
 }
 
 static void
 ucp_handle_time(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
 {
-    char        strval[BUFSIZ];
+    gint        idx, len;
+    char        *strval;
     time_t      tval;
     nstime_t    tmptime;
-    int                 tmpoff = *offset;
-    int                 idx = 0;
 
-    while ((strval[idx++] = tvb_get_guint8(tvb, tmpoff++)) != '/')
-       ;
-    if (idx > 1) {
-       strval[--idx] = '\0';
+    idx = tvb_find_guint8(tvb, *offset, -1, '/');
+    if (idx == -1) {
+       /* Force the appropriate exception to be thrown. */
+       len = tvb_length_remaining(tvb, *offset);
+       tvb_ensure_bytes_exist(tvb, *offset, len + 1);
+    } else
+       len = idx - *offset;
+    strval = tvb_get_string(tvb, *offset, len);
+    if (len > 0) {
        tval = ucp_mktime(strval);
        tmptime.secs  = tval;
        tmptime.nsecs = 0;
        proto_tree_add_time(tree, field, tvb, *offset, idx, &tmptime);
     }
-    *offset = tmpoff;
+    g_free(strval);
+    *offset += len;
+    if (idx != -1)
+       *offset += 1;   /* skip terminating '/' */
 }
 
 static void
@@ -773,7 +832,7 @@ ucp_handle_data(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
 
     while (tvb_get_guint8(tvb, tmpoff++) != '/')
        ;
-    if ((tmpoff - *offset) > 1)        
+    if ((tmpoff - *offset) > 1)
        proto_tree_add_item(tree, field, tvb, *offset,
                            tmpoff - *offset - 1, FALSE);
     *offset = tmpoff;
@@ -797,9 +856,7 @@ ucp_handle_data(proto_tree *tree, tvbuff_t *tvb, int field, int *offset)
 static void
 ucp_handle_mt(proto_tree *tree, tvbuff_t *tvb, int *offset)
 {
-    char                strval[BUFSIZ];
     guint               intval;
-    int                         idx;
 
     intval = ucp_handle_byte(tree, tvb, hf_ucp_parm_MT, offset);
     switch (intval) {
@@ -809,9 +866,11 @@ ucp_handle_mt(proto_tree *tree, tvbuff_t *tvb, int *offset)
            ucp_handle_string(tree, tvb, hf_ucp_parm_NB, offset);
            /* fall through here for the data piece     */
        case '2':
-       case '3':
            ucp_handle_data(tree, tvb, hf_ucp_data_section, offset);
            break;
+       case '3':
+            ucp_handle_IRAstring(tree, tvb, hf_ucp_parm_AMsg, offset);
+            break;
        case '5':
            ucp_handle_byte(tree, tvb, hf_ucp_parm_PNC, offset);
            ucp_handle_string(tree, tvb, hf_ucp_parm_LNo, offset);
@@ -862,6 +921,9 @@ ucp_handle_XSer(proto_tree *tree, tvbuff_t *tvb)
  */
 #define UcpHandleString(field) ucp_handle_string(tree, tvb, (field), &offset)
 
+#define UcpHandleIRAString(field) \
+                        ucp_handle_IRAstring(tree, tvb, (field), &offset)
+
 #define UcpHandleByte(field)   ucp_handle_byte(tree, tvb, (field), &offset)
 
 #define        UcpHandleInt(field)     ucp_handle_int(tree, tvb, (field), &offset)
@@ -1452,9 +1514,12 @@ add_5xO(proto_tree *tree, tvbuff_t *tvb)
     UcpHandleByte(hf_ucp_parm_Dst);
     UcpHandleInt(hf_ucp_parm_Rsn);
     UcpHandleTime(hf_ucp_parm_DSCTS);
-    UcpHandleByte(hf_ucp_parm_MT);
+    intval = UcpHandleByte(hf_ucp_parm_MT);
     UcpHandleString(hf_ucp_parm_NB);
-    UcpHandleData(hf_ucp_data_section);
+    if (intval != '3')
+        UcpHandleData(hf_ucp_data_section);
+    else
+        UcpHandleIRAString(hf_ucp_parm_AMsg);
     UcpHandleByte(hf_ucp_parm_MMS);
     UcpHandleByte(hf_ucp_parm_PR);
     UcpHandleByte(hf_ucp_parm_DCs);
@@ -1503,8 +1568,8 @@ add_6xO(proto_tree *tree, tvbuff_t *tvb, guint8 OT)
     } else {
        UcpHandleByte(hf_ucp_parm_STYP1);
     }
-    UcpHandleData(hf_ucp_parm_PWD);
-    UcpHandleData(hf_ucp_parm_NPWD);
+    UcpHandleIRAString(hf_ucp_parm_PWD);
+    UcpHandleIRAString(hf_ucp_parm_NPWD);
     UcpHandleString(hf_ucp_parm_VERS);
     UcpHandleString(hf_ucp_parm_LAdC);
     UcpHandleByte(hf_ucp_parm_LTON);
@@ -1520,6 +1585,7 @@ add_6xO(proto_tree *tree, tvbuff_t *tvb, guint8 OT)
  * End of convenient shorthands
  */
 #undef UcpHandleString
+#undef UcpHandleIRAString
 #undef UcpHandleByte
 #undef UcpHandleInt
 #undef UcpHandleTime
@@ -1555,7 +1621,7 @@ dissect_ucp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        return FALSE;
 
     /*
-     * Try getting the operation-type and whether it's a request/response 
+     * Try getting the operation-type and whether it's a request/response
      */
     O_R = tvb_get_guint8(tvb, UCP_O_R_OFFSET);
     if (match_strval(O_R, vals_hdr_O_R) == NULL)
@@ -1584,6 +1650,7 @@ dissect_ucp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     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);
@@ -1655,92 +1722,96 @@ dissect_ucp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        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  0:
+               O_R == 'O' ? add_00O(sub_tree,tmp_tvb) : add_00R(sub_tree,tmp_tvb);
+               break;
            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;
@@ -1938,6 +2009,13 @@ proto_register_ucp(void)
              HFILL
            }
        },
+       { &hf_ucp_parm_AMsg,
+           { "AMsg", "ucp.parm.AMsg",
+             FT_STRING, BASE_NONE, NULL, 0x00,
+             "The alphanumeric message that is being sent.",
+             HFILL
+           }
+       },
        { &hf_ucp_parm_LNo,
            { "LNo", "ucp.parm.LNo",
              FT_STRING, BASE_NONE, NULL, 0x00,
@@ -2087,7 +2165,7 @@ proto_register_ucp(void)
        },
        { &hf_ucp_parm_R_T,
            { "R_T", "ucp.parm.R_T",
-             FT_STRING, BASE_NONE, NULL, 0x00,
+             FT_UINT8, BASE_DEC, VALS(vals_parm_R_T), 0x00,
              "Message number.",
              HFILL
            }
@@ -2381,14 +2459,14 @@ proto_register_ucp(void)
        },
        { &hf_ucp_parm_PWD,
            { "PWD", "ucp.parm.PWD",
-             FT_NONE, BASE_DEC, NULL, 0x00,
+             FT_STRING, BASE_NONE, NULL, 0x00,
              "Current password.",
              HFILL
            }
        },
        { &hf_ucp_parm_NPWD,
            { "NPWD", "ucp.parm.NPWD",
-             FT_NONE, BASE_DEC, NULL, 0x00,
+             FT_STRING, BASE_NONE, NULL, 0x00,
              "New password.",
              HFILL
            }
@@ -2481,6 +2559,7 @@ proto_register_ucp(void)
     /* Setup protocol subtree array */
     static gint *ett[] = {
        &ett_ucp,
+       &ett_sub,
        &ett_XSer
     };
     /* Register the protocol name and description */