warning: ISO C does not allow extra ; outside of a function
[obnox/wireshark/wip.git] / packet-wtp.c
index 843a011e9c880ac424559851881da8c28023bb7b..842fa7770fd6957f7d8f1020de6b2658d7df7745 100644 (file)
@@ -2,7 +2,7 @@
  *
  * Routines to dissect WTP component of WAP traffic.
  *
- * $Id: packet-wtp.c,v 1.46 2003/05/08 18:49:20 guy Exp $
+ * $Id: packet-wtp.c,v 1.55 2003/12/21 05:51:34 jmayer Exp $
  *
  * Ethereal - Network traffic analyzer
  * By Gerald Combs <gerald@ethereal.com>
@@ -198,6 +198,7 @@ static int hf_wtp_fragment_error            = HF_EMPTY;
 
 /* Initialize the subtree pointers */
 static gint ett_wtp                            = ETT_EMPTY;
+static gint ett_wtp_sub_pdu_tree       = ETT_EMPTY;
 static gint ett_header                                 = ETT_EMPTY;
 static gint ett_tpilist                        = ETT_EMPTY;
 static gint ett_wsp_fragments                  = ETT_EMPTY;
@@ -308,7 +309,7 @@ wtp_handle_tpi(proto_tree *tree, tvbuff_t *tvb)
 static void
 dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
-    char       szInfo[50];
+    static GString *szInfo = NULL;
     int                offCur          = 0; /* current offset from start of WTP data */
 
     unsigned char  b0;
@@ -327,7 +328,6 @@ dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 
     char               pdut;
     char               clsTransaction  = ' ';
-    int                        cchInfo;
     int                        numMissing = 0;         /* Number of missing packets in a negative ack */
     int                        i;
     tvbuff_t           *wsp_tvb = NULL;
@@ -335,6 +335,9 @@ dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     guint8             psn = 0;                /* Packet sequence number*/
     guint16            TID = 0;                /* Transaction-Id       */
 
+    if (szInfo == NULL)
+       szInfo = g_string_sized_new(32);
+
     b0 = tvb_get_guint8 (tvb, offCur + 0);
     /* Discover Concatenated PDUs */
     if (b0 == 0) {
@@ -344,7 +347,7 @@ dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        if (tree) {
            ti = proto_tree_add_item(tree, proto_wtp,
                                    tvb, offCur, 1, bo_little_endian);
-           wtp_tree = proto_item_add_subtree(ti, ett_wtp);
+           wtp_tree = proto_item_add_subtree(ti, ett_wtp_sub_pdu_tree);
        }
        offCur = 1;
        i = 1;
@@ -364,7 +367,7 @@ dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
            if (i > 1 && check_col(pinfo->cinfo, COL_INFO)) {
                col_append_str(pinfo->cinfo, COL_INFO, ", ");
            }
-           wsp_tvb = tvb_new_subset(tvb, offCur + c_fieldlen, -1, c_pdulen);
+           wsp_tvb = tvb_new_subset(tvb, offCur + c_fieldlen, c_pdulen, c_pdulen);
            dissect_wtp_common(wsp_tvb, pinfo, wtp_tree);
            offCur += c_fieldlen + c_pdulen;
            i++;
@@ -376,7 +379,7 @@ dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     pdut = pdu_type(b0);
 
     /* Develop the string to put in the Info column */
-    cchInfo = snprintf(szInfo, sizeof( szInfo ), "WTP %s",
+    g_string_sprintf(szInfo, "WTP %s",
                    val_to_str(pdut, vals_pdu_type, "Unknown PDU type 0x%x"));
 
     switch (pdut) {
@@ -385,8 +388,7 @@ dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
            TID = tvb_get_ntohs(tvb, offCur + 1);
            psn = 0;
            clsTransaction = transaction_class(tvb_get_guint8(tvb, offCur + 3));
-           snprintf(szInfo + cchInfo, sizeof(szInfo) - cchInfo,
-                    " Class %d", clsTransaction);
+           g_string_sprintfa(szInfo, " Class %d", clsTransaction);
            cbHeader = 4;
            break;
 
@@ -423,7 +425,7 @@ dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
            break;
     };
     if (fRID) {
-       strcat( szInfo, " R" );
+       g_string_append( szInfo, " R" );
     };
     if (fCon) {                                /* Scan variable part (TPI's),  */
                                        /* determine length of it       */
@@ -452,9 +454,9 @@ dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        ((tvb_length_remaining(tvb, offCur + cbHeader + vHeader) <= 0) ||
         (pdut == ACK) || (pdut==NEGATIVE_ACK) || (pdut==ABORT)) ) {
 #ifdef DEBUG
-       fprintf(stderr, "dissect_wtp: (6) About to set info_col header to %s\n", szInfo);
+       fprintf(stderr, "dissect_wtp: (6) About to set info_col header to %s\n", szInfo->str);
 #endif
-       col_append_str(pinfo->cinfo, COL_INFO, szInfo);
+       col_append_str(pinfo->cinfo, COL_INFO, szInfo->str);
     };
     /* In the interest of speed, if "tree" is NULL, don't do any work not
        necessary to generate protocol tree items. */
@@ -594,9 +596,13 @@ dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
     }
     /*
      * Any remaining data ought to be WSP data (if not WTP ACK, NACK
-     * or ABORT pdu), so hand off (defragmented) to the WSP dissector
+     * or ABORT pdu), so hand off (defragmented) to the WSP dissector.
+     * Note that the last packet of a fragmented WTP message needn't
+     * contain any data, so we allow payloadless packets to be
+     * reassembled.  (XXX - does the reassembly code handle this
+     * for packets other than the last packet?)
      */
-    if ((tvb_reported_length_remaining(tvb, offCur + cbHeader + vHeader) > 0) &&
+    if ((tvb_reported_length_remaining(tvb, offCur + cbHeader + vHeader) >= 0) &&
        ! ((pdut==ACK) || (pdut==NEGATIVE_ACK) || (pdut==ABORT)))
     {
        int     dataOffset = offCur + cbHeader + vHeader;
@@ -613,6 +619,7 @@ dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
                            wtp_fragment_table, psn, dataLen, !fTTR);
            if (fd_head != NULL)                /* Reassembled  */
            {
+               /* Reassembly is complete; show the reassembled PDU */
                wsp_tvb = tvb_new_real_data(fd_head->data,
                                            fd_head->len,
                                            fd_head->len);
@@ -629,8 +636,11 @@ dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
            }
            else
            {
+               /* Reassembly isn't complete; just show the fragment */
                if (check_col(pinfo->cinfo, COL_INFO))          /* Won't call WSP so display */
-                   col_append_str(pinfo->cinfo, COL_INFO, szInfo);
+                   col_append_str(pinfo->cinfo, COL_INFO, szInfo->str);
+               if (tree != NULL)
+                   proto_tree_add_text(wtp_tree, tvb, dataOffset, -1, "Payload");
            }
            pinfo->fragmented = save_fragmented;
        }
@@ -638,10 +648,28 @@ dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
        {
            /*
             * Normal packet, or not all the fragment data is available;
-            * call next dissector.
+            * call next dissector, unless this is a segment of a
+            * segmented invoke or result and isn't the first segment.
             */
-           wsp_tvb = tvb_new_subset(tvb, dataOffset, -1, -1);
-           call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
+           if ((pdut == SEGMENTED_INVOKE || pdut == SEGMENTED_RESULT) &&
+                       psn != 0) {
+               /*
+                * This is a segmented invoke or result, and not the first
+                * segment; just show it as a segmented invoke or result,
+                * don't try to dissect its payload.
+                */
+               if (check_col(pinfo->cinfo, COL_INFO))
+                   col_add_fstr(pinfo->cinfo, COL_INFO,
+                                "WTP %s (%u)",
+                                (pdut == SEGMENTED_INVOKE ?
+                                 "Segmented Invoke" : "Segmented Result"),
+                                psn);
+               if (tree != NULL)
+                   proto_tree_add_text(wtp_tree, tvb, dataOffset, -1, "Payload");
+           } else {
+               wsp_tvb = tvb_new_subset(tvb, dataOffset, -1, -1);
+               call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
+           }
        }
     }
 }
@@ -671,7 +699,7 @@ dissect_wtp_fromudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
  * XXX - can this be called from any other dissector?
  */
 static void
-dissect_wtp_fromwap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_wtp_fromwtls(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
 {
     if (check_col(pinfo->cinfo, COL_PROTOCOL))
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "WTLS+WTP+WSP" );
@@ -920,6 +948,7 @@ proto_register_wtp(void)
     /* Setup protocol subtree array */
     static gint *ett[] = {
        &ett_wtp,
+       &ett_wtp_sub_pdu_tree,
        &ett_header,
        &ett_tpilist,
        &ett_wsp_fragments,
@@ -930,7 +959,7 @@ proto_register_wtp(void)
     proto_wtp = proto_register_protocol(
        "Wireless Transaction Protocol",   /* protocol name for use by ethereal */
        "WTP",                             /* short version of name */
-       "wap-wsp-wtp"                      /* Abbreviated protocol name, should Match IANA
+       "wtp"                      /* Abbreviated protocol name, should Match IANA
                                            < URL:http://www.isi.edu/in-notes/iana/assignments/port-numbers/ >
                                            */
     );
@@ -939,10 +968,10 @@ proto_register_wtp(void)
     proto_register_field_array(proto_wtp, hf, array_length(hf));
     proto_register_subtree_array(ett, array_length(ett));
 
-    register_dissector("wtp", dissect_wtp_fromwap, proto_wtp);
+    register_dissector("wtp-wtls", dissect_wtp_fromwtls, proto_wtp);
     register_dissector("wtp-udp", dissect_wtp_fromudp, proto_wtp);
     register_init_routine(wtp_defragment_init);
-};
+}
 
 void
 proto_reg_handoff_wtp(void)
@@ -957,4 +986,5 @@ proto_reg_handoff_wtp(void)
 
     wtp_fromudp_handle = find_dissector("wtp-udp");
     dissector_add("udp.port", UDP_PORT_WTP_WSP, wtp_fromudp_handle);
+    dissector_add("smpp.udh.port", UDP_PORT_WTP_WSP, wtp_fromudp_handle);
 }