*
* 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>
/* 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;
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;
char pdut;
char clsTransaction = ' ';
- int cchInfo;
int numMissing = 0; /* Number of missing packets in a negative ack */
int i;
tvbuff_t *wsp_tvb = NULL;
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) {
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;
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++;
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) {
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;
break;
};
if (fRID) {
- strcat( szInfo, " R" );
+ g_string_append( szInfo, " R" );
};
if (fCon) { /* Scan variable part (TPI's), */
/* determine length of it */
((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. */
}
/*
* 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;
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);
}
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;
}
{
/*
* 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);
+ }
}
}
}
* 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" );
/* Setup protocol subtree array */
static gint *ett[] = {
&ett_wtp,
+ &ett_wtp_sub_pdu_tree,
&ett_header,
&ett_tpilist,
&ett_wsp_fragments,
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/ >
*/
);
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)
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);
}