*
* $Id$
*
- * Ethereal - Network traffic analyzer
- * By Gerald Combs <gerald@ethereal.com>
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* This program is free software; you can redistribute it and/or
* www.etsi.org).
* Includes the extension of EMI-UCP interface (V4.0, May 2001, www.cmgwds.com)
*
+ * Support for statistics using the Stats Tree API added by
+ * Abhik Sarkar <sarkar.abhik@gmail.com>
+ *
*/
#ifdef HAVE_CONFIG_H
#include <glib.h>
#include <epan/packet.h>
-/* #include "packet-ucp.h" */ /* We autoregister */
+#include <epan/prefs.h>
+#include <epan/emem.h>
+#include <epan/stats_tree.h>
+
+#include "packet-tcp.h"
/* Prototypes */
-static void dissect_ucp(tvbuff_t *, packet_info *, proto_tree *);
+static void dissect_ucp_common(tvbuff_t *, packet_info *, proto_tree *);
+
+/* Tap Record */
+typedef struct _ucp_tap_rec_t {
+ guint message_type; /* 0 = Operation; 1 = Result */
+ guint operation; /* Operation Type */
+ guint result; /* 0 = Success; Non 0 = Error Code */
+} ucp_tap_rec_t;
+
+/* Preferences */
+gboolean ucp_desegment = TRUE;
+/* STX + TRN 2 num. char.+ LEN 5 num. char. + O/R Char 'O' or 'R' + OT 2 num. char. */
+#define UCP_HEADER_SIZE 11
/*
* Convert ASCII-hex character to binary equivalent. No checks, assume
#define UCP_MALFORMED -1 /* Not a valid PDU */
#define UCP_SHORTENED -2 /* May be valid but short */
-#define UCP_INV_CHK -3 /* Checksum doesn't add up */
+#define UCP_INV_CHK -3 /* Checksum doesn't add up */
#define UCP_O_R_OFFSET 10 /* Location of O/R field*/
#define UCP_OT_OFFSET 12 /* Location of OT field */
static int hf_ucp_hdr_O_R = -1;
static int hf_ucp_hdr_OT = -1;
+/*
+ * Stats section
+ */
+static int st_ucp_messages = -1;
+static int st_ucp_ops = -1;
+static int st_ucp_res = -1;
+static int st_ucp_results = -1;
+static int st_ucp_results_pos = -1;
+static int st_ucp_results_neg = -1;
+
+static gchar* st_str_ucp = "UCP Messages";
+static gchar* st_str_ops = "Operations";
+static gchar* st_str_res = "Results";
+static gchar* st_str_ucp_res = "UCP Results Acks/Nacks";
+static gchar* st_str_pos = "Positive";
+static gchar* st_str_neg = "Negative";
+
/*
* Data (variable) section
*/
static gint ett_sub = -1;
static gint ett_XSer = -1;
+/* Tap */
+static int ucp_tap = -1;
+
/*
* Value-arrays for certain field-contents
*/
{ 13, "Legitimisation code for priority call, failure" },
{ 14, "Urgent message not allowed" },
{ 15, "Legitimisation code for urgent message, failure" },
- { 16, "Reverse charging not alllowed" },
+ { 16, "Reverse charging not allowed" },
{ 17, "Legitimisation code for rev. charging, failure" },
{ 18, "Deferred delivery not allowed" },
{ 19, "New AC not valid" },
{ 38, "Message forwarded" },
{ 50, "Low network status" },
{ 51, "Legitimisation code for standard text, failure" },
- { 53, "Operation partially successfull" },
- { 54, "Operation not successfull" },
+ { 53, "Operation partially successful" },
+ { 54, "Operation not successful" },
{ 55, "System error" },
{ 57, "AdC already a member of GAdC address list" },
{ 58, "AdC not a member of GAdC address list" },
};
static const value_string vals_parm_LRR[] = {
- { '1', "Leg. code for repitition requested" },
+ { '1', "Leg. code for repetition requested" },
{ 0, NULL },
};
static const value_string vals_parm_SSTAT[] = {
{ '0', "All services" },
- { '1', "All in the moment active servics" },
+ { '1', "All in the moment active services" },
{ '2', "Call diversion" },
{ '3', "Roaming information status" },
{ '4', "Call barring status" },
{ 5, "[Privacy Indicator] TDMA information exchange" },
{ 6, "[Urgency Indicator] TDMA information exchange" },
{ 7, "[Acknowledgement Request] TDMA information exchange" },
- { 8, "[Messsage Updating] TDMA information exchange" },
+ { 8, "[Message Updating] TDMA information exchange" },
{ 9, "[Call Back Number] TDMA information exchange" },
{ 10, "[Response Code] TDMA information exchange" },
{ 11, "[Teleservice ID] TDMA information exchange" },
{ 0, NULL },
};
+/* For statistics */
+static void
+ucp_stats_tree_init(stats_tree* st)
+{
+ st_ucp_messages = stats_tree_create_node(st, st_str_ucp, 0, TRUE);
+ st_ucp_ops = stats_tree_create_node(st, st_str_ops, st_ucp_messages, TRUE);
+ st_ucp_res = stats_tree_create_node(st, st_str_res, st_ucp_messages, TRUE);
+ st_ucp_results = stats_tree_create_node(st, st_str_ucp_res, 0, TRUE);
+ st_ucp_results_pos = stats_tree_create_node(st, st_str_pos, st_ucp_results, TRUE);
+ st_ucp_results_neg = stats_tree_create_node(st, st_str_neg, st_ucp_results, TRUE);
+}
+
+static int
+ucp_stats_tree_per_packet(stats_tree *st, /* st as it was passed to us */
+ packet_info *pinfo _U_,
+ epan_dissect_t *edt _U_,
+ const void *p) /* Used for getting UCP stats */
+{
+ ucp_tap_rec_t* tap_rec = (ucp_tap_rec_t*)p;
+
+ tick_stat_node(st, st_str_ucp, 0, TRUE);
+
+ if (tap_rec->message_type == 0) /* Operation */
+ {
+ tick_stat_node(st, st_str_ops, st_ucp_messages, TRUE);
+ tick_stat_node(st, val_to_str(tap_rec->operation, vals_hdr_OT,
+ "Unknown OT: %d"), st_ucp_ops, FALSE);
+ }
+ else /* Result */
+ {
+ tick_stat_node(st, st_str_res, st_ucp_messages, TRUE);
+ tick_stat_node(st, val_to_str(tap_rec->operation, vals_hdr_OT,
+ "Unknown OT: %d"), st_ucp_res, FALSE);
+
+ tick_stat_node(st, st_str_ucp_res, 0, TRUE);
+
+ if (tap_rec->result == 0) /* Positive Result */
+ {
+ tick_stat_node(st, st_str_pos, st_ucp_results, FALSE);
+ }
+ else /* Negative Result */
+ {
+ tick_stat_node(st, st_str_neg, st_ucp_results, TRUE);
+ tick_stat_node(st, val_to_str(tap_rec->result, vals_parm_EC,
+ "Unknown EC: %d"), st_ucp_results_neg, FALSE);
+ }
+ }
+
+ return 1;
+}
+
/*!
* Checks whether the PDU looks a bit like UCP and checks the checksum
*
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;
}
tvb_ensure_bytes_exist(tvb, *offset, len + 1);
} else
len = idx - *offset;
- strval = tvb_get_ephemeral_string(tvb, *offset, len);
+ strval = (gchar*)tvb_get_ephemeral_string(tvb, *offset, len);
if (len > 0) {
intval = atoi(strval);
proto_tree_add_uint(tree, field, tvb, *offset, idx, intval);
tvb_ensure_bytes_exist(tvb, *offset, len + 1);
} else
len = idx - *offset;
- strval = tvb_get_ephemeral_string(tvb, *offset, len);
+ strval = (gchar*)tvb_get_ephemeral_string(tvb, *offset, len);
if (len > 0) {
tval = ucp_mktime(strval);
tmptime.secs = tval;
}
static void
-add_00R(proto_tree *tree, tvbuff_t *tvb)
+add_00R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
{
int offset = 1;
guint intval;
UcpHandleInt(hf_ucp_parm_NoN);
UcpHandleInt(hf_ucp_parm_NoA);
UcpHandleInt(hf_ucp_parm_NoB);
+
+ tap_rec->result = 0;
} else {
- UcpHandleInt(hf_ucp_parm_EC);
+ tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
UcpHandleString(hf_ucp_parm_SM);
}
}
}
static void
-add_01R(proto_tree *tree, tvbuff_t *tvb)
+add_01R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
{
int offset = 1;
guint intval;
intval = UcpHandleByte(hf_ucp_parm_ACK);
if (intval == 'N')
- UcpHandleInt(hf_ucp_parm_EC);
+ tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
+ else
+ tap_rec->result = 0;
UcpHandleString(hf_ucp_parm_SM);
}
ucp_handle_mt(tree, tvb, &offset);
}
-#define add_02R(a, b) add_01R(a,b)
+#define add_02R(a, b, c) add_01R(a, b, c)
static void
add_03O(proto_tree *tree, tvbuff_t *tvb)
ucp_handle_mt(tree, tvb, &offset);
}
-#define add_03R(a, b) add_01R(a,b)
+#define add_03R(a, b, c) add_01R(a, b, c)
static void
add_04O(proto_tree *tree, tvbuff_t *tvb)
}
static void
-add_04R(proto_tree *tree, tvbuff_t *tvb)
+add_04R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
{
int offset = 1;
guint intval;
for (idx = 0; idx < intval; idx++)
UcpHandleString(hf_ucp_parm_AdC);
UcpHandleString(hf_ucp_parm_GAdC);
+ tap_rec->result = 0;
} else
- UcpHandleInt(hf_ucp_parm_EC);
+ tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
UcpHandleString(hf_ucp_parm_SM);
}
UcpHandleByte(hf_ucp_parm_A_D);
}
-#define add_05R(a, b) add_01R(a, b)
+#define add_05R(a, b, c) add_01R(a, b, c)
static void
add_06O(proto_tree *tree, tvbuff_t *tvb)
}
static void
-add_06R(proto_tree *tree, tvbuff_t *tvb)
+add_06R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
{
int offset = 1;
guint intval;
if (intval == 'A') {
UcpHandleTime(hf_ucp_parm_CT);
UcpHandleString(hf_ucp_parm_AAC);
+ tap_rec->result = 0;
} else
- UcpHandleInt(hf_ucp_parm_EC);
+ tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
UcpHandleString(hf_ucp_parm_SM);
}
UcpHandleString(hf_ucp_parm_NAC);
}
-#define add_07R(a, b) add_01R(a, b)
+#define add_07R(a, b, c) add_01R(a, b, c)
static void
add_08O(proto_tree *tree, tvbuff_t *tvb)
UcpHandleString(hf_ucp_parm_LST);
}
-#define add_08R(a, b) add_01R(a, b)
+#define add_08R(a, b, c) add_01R(a, b, c)
static void
add_09O(proto_tree *tree, tvbuff_t *tvb)
}
static void
-add_09R(proto_tree *tree, tvbuff_t *tvb)
+add_09R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
{
int offset = 1;
guint intval;
intval = UcpHandleInt(hf_ucp_parm_NPL);
for (idx = 0; idx < intval; idx++)
UcpHandleString(hf_ucp_parm_LST);
+ tap_rec->result = 0;
} else
- UcpHandleInt(hf_ucp_parm_EC);
+ tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
UcpHandleString(hf_ucp_parm_SM);
}
UcpHandleInt(hf_ucp_parm_CS);
}
-#define add_10R(a, b) add_01R(a, b)
+#define add_10R(a, b, c) add_01R(a, b, c)
#define add_11O(a, b) add_06O(a, b) /* Request roaming info */
static void
-add_11R(proto_tree *tree, tvbuff_t *tvb)
+add_11R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
{
int offset = 1;
guint intval;
intval = UcpHandleInt(hf_ucp_parm_NPL);
for (idx = 0; idx < intval; idx++)
UcpHandleString(hf_ucp_parm_GA);
+ tap_rec->result = 0;
} else
- UcpHandleInt(hf_ucp_parm_EC);
+ tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
UcpHandleString(hf_ucp_parm_SM);
}
UcpHandleString(hf_ucp_parm_GA);
}
-#define add_12R(a, b) add_01R(a, b)
+#define add_12R(a, b, c) add_01R(a, b, c)
#define add_13O(a, b) add_06O(a, b) /* Roaming reset */
-#define add_13R(a, b) add_01R(a, b)
+#define add_13R(a, b, c) add_01R(a, b, c)
static void
add_14O(proto_tree *tree, tvbuff_t *tvb)
}
static void
-add_14R(proto_tree *tree, tvbuff_t *tvb)
+add_14R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
{
int offset = 1;
guint intval;
*/
for (idx = 0; idx < intval; idx++)
UcpHandleData(hf_ucp_data_section);
+ tap_rec->result = 0;
} else {
- UcpHandleInt(hf_ucp_parm_EC);
- UcpHandleString(hf_ucp_parm_SM);
+ tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
+ UcpHandleString(hf_ucp_parm_SM);
}
}
UcpHandleTime(hf_ucp_parm_SP);
}
-#define add_15R(a, b) add_01R(a, b)
+#define add_15R(a, b, c) add_01R(a, b, c)
#define add_16O(a, b) add_06O(a, b) /* Cancel call barring */
-#define add_16R(a, b) add_01R(a, b)
+#define add_16R(a, b, c) add_01R(a, b, c)
static void
add_17O(proto_tree *tree, tvbuff_t *tvb)
UcpHandleTime(hf_ucp_parm_SP);
}
-#define add_17R(a, b) add_01R(a, b)
+#define add_17R(a, b, c) add_01R(a, b, c)
#define add_18O(a, b) add_06O(a, b) /* Cancel call diversion */
-#define add_18R(a, b) add_01R(a, b)
+#define add_18R(a, b, c) add_01R(a, b, c)
static void
add_19O(proto_tree *tree, tvbuff_t *tvb)
UcpHandleTime(hf_ucp_parm_SP);
}
-#define add_19R(a, b) add_01R(a, b)
+#define add_19R(a, b, c) add_01R(a, b, c)
#define add_20O(a, b) add_06O(a, b) /* Cancel deferred delivery */
-#define add_20R(a, b) add_01R(a, b)
+#define add_20R(a, b, c) add_01R(a, b, c)
#define add_21O(a, b) add_06O(a, b) /* All features reset */
-#define add_21R(a, b) add_01R(a, b)
+#define add_21R(a, b, c) add_01R(a, b, c)
static void
add_22O(proto_tree *tree, tvbuff_t *tvb)
UcpHandleInt(hf_ucp_parm_CS);
}
-#define add_22R(a, b) add_01R(a, b)
+#define add_22R(a, b, c) add_01R(a, b, c)
static void
add_23O(proto_tree *tree, tvbuff_t *tvb)
}
static void
-add_23R(proto_tree *tree, tvbuff_t *tvb)
+add_23R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
{
int offset = 1;
guint intval;
intval = UcpHandleInt(hf_ucp_parm_NPL);
for (idx = 0; idx < intval; idx++)
UcpHandleInt(hf_ucp_hdr_OT);
+ tap_rec->result = 0;
} else
- UcpHandleInt(hf_ucp_parm_EC);
+ tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
UcpHandleString(hf_ucp_parm_SM);
}
}
static void
-add_24R(proto_tree *tree, tvbuff_t *tvb)
+add_24R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
{
int offset = 1;
guint intval;
intval = UcpHandleInt(hf_ucp_parm_NMESS);
}
}
+ tap_rec->result = 0;
} else
- UcpHandleInt(hf_ucp_parm_EC);
+ tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
UcpHandleString(hf_ucp_parm_SM);
}
}
static void
-add_30R(proto_tree *tree, tvbuff_t *tvb)
+add_30R(proto_tree *tree, tvbuff_t *tvb, ucp_tap_rec_t *tap_rec)
{
int offset = 1;
guint intval;
intval = UcpHandleByte(hf_ucp_parm_ACK);
- if (intval == 'A')
+ if (intval == 'A') {
UcpHandleTime(hf_ucp_parm_MVP);
- else
- UcpHandleInt(hf_ucp_parm_EC);
+ tap_rec->result = 0;
+ } else {
+ tap_rec->result = UcpHandleInt(hf_ucp_parm_EC);
+ }
UcpHandleString(hf_ucp_parm_SM);
}
UcpHandleInt(hf_ucp_parm_PID);
}
-#define add_31R(a, b) add_01R(a, b)
+#define add_31R(a, b, c) add_01R(a, b, c)
static void
add_5xO(proto_tree *tree, tvbuff_t *tvb)
UcpHandleData(hf_ucp_parm_RES5);
}
-#define add_5xR(a, b) add_30R(a, b)
+#define add_5xR(a, b,c ) add_30R(a, b, c)
static void
add_6xO(proto_tree *tree, tvbuff_t *tvb, guint8 OT)
UcpHandleByte(hf_ucp_parm_LNPI);
UcpHandleInt(hf_ucp_parm_OPID);
UcpHandleData(hf_ucp_parm_RES1);
- UcpHandleData(hf_ucp_parm_RES2);
+ if (OT == 61) {
+ UcpHandleData(hf_ucp_parm_RES2);
+ }
}
-#define add_6xR(a, b) add_01R(a, b)
+#define add_6xR(a, b, c) add_01R(a, b, c)
/*
* End of convenient shorthands
/*
* Ok, looks like a valid packet, go dissect.
*/
- dissect_ucp(tvb, pinfo, tree);
+
+ dissect_ucp_common(tvb, pinfo, tree);
return TRUE;
}
+static guint
+get_ucp_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb, int offset)
+{
+ guint intval=0;
+ int i;
+
+ offset = offset + 4;
+ for (i = 0; i < UCP_LEN_LEN; i++) { /* Length */
+ intval = 10 * intval +
+ (tvb_get_guint8(tvb, offset) - '0');
+ offset++;
+ }
+
+ return intval + 2;
+}
+
+
+static void
+dissect_ucp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+{
+ tcp_dissect_pdus(tvb, pinfo, tree, ucp_desegment, UCP_HEADER_SIZE,
+ get_ucp_pdu_len, dissect_ucp_common);
+}
/*
* The actual dissector
*/
static void
-dissect_ucp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
+dissect_ucp_common(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 OT; /* Operation type */
guint intval;
int i;
+ ucp_tap_rec_t* tap_rec; /* Tap record */
/* Set up structures needed to add the protocol subtree and manage it */
proto_item *ti;
proto_tree *sub_tree;
tvbuff_t *tmp_tvb;
+ /* Make entries in Protocol column */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "UCP");
+
+ /* 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){
+ proto_tree_add_text(tree, tvb, 0, -1,"UCP_STX missing, this is not a new packet");
+ return;
+ }
+
+ /* Get data needed for dissect_ucp_common */
+ result = check_ucp(tvb, &endpkt);
+
O_R = tvb_get_guint8(tvb, UCP_O_R_OFFSET);
/*
* So do an atoi() on the operation type
OT = tvb_get_guint8(tvb, UCP_OT_OFFSET) - '0';
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->cinfo, COL_PROTOCOL))
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "UCP");
+ /* Create Tap record */
+ tap_rec = ep_alloc0(sizeof(ucp_tap_rec_t));
+ tap_rec->message_type = (O_R == 'O' ? 0 : 1);
+ tap_rec->operation = OT;
+ /* Make entries in Info column on summary display */
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "UCP");
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));
+ val_to_str(O_R, vals_hdr_O_R, "Unknown (%d)"));
if (result == UCP_SHORTENED)
col_append_str(pinfo->cinfo, COL_INFO, " [short packet]");
else if (result == UCP_INV_CHK)
*/
if (result == UCP_SHORTENED)
return;
- tmp_tvb = tvb_new_subset(tvb, offset, -1, -1);
+ tmp_tvb = tvb_new_subset_remaining(tvb, offset);
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);
+ O_R == 'O' ? add_00O(sub_tree,tmp_tvb) : add_00R(sub_tree,tmp_tvb, tap_rec);
break;
case 1:
- O_R == 'O' ? add_01O(sub_tree,tmp_tvb) : add_01R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_01O(sub_tree,tmp_tvb) : add_01R(sub_tree,tmp_tvb, tap_rec);
break;
case 2:
- O_R == 'O' ? add_02O(sub_tree,tmp_tvb) : add_02R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_02O(sub_tree,tmp_tvb) : add_02R(sub_tree,tmp_tvb, tap_rec);
break;
case 3:
- O_R == 'O' ? add_03O(sub_tree,tmp_tvb) : add_03R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_03O(sub_tree,tmp_tvb) : add_03R(sub_tree,tmp_tvb, tap_rec);
break;
case 4:
- O_R == 'O' ? add_04O(sub_tree,tmp_tvb) : add_04R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_04O(sub_tree,tmp_tvb) : add_04R(sub_tree,tmp_tvb, tap_rec);
break;
case 5:
- O_R == 'O' ? add_05O(sub_tree,tmp_tvb) : add_05R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_05O(sub_tree,tmp_tvb) : add_05R(sub_tree,tmp_tvb, tap_rec);
break;
case 6:
- O_R == 'O' ? add_06O(sub_tree,tmp_tvb) : add_06R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_06O(sub_tree,tmp_tvb) : add_06R(sub_tree,tmp_tvb, tap_rec);
break;
case 7:
- O_R == 'O' ? add_07O(sub_tree,tmp_tvb) : add_07R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_07O(sub_tree,tmp_tvb) : add_07R(sub_tree,tmp_tvb, tap_rec);
break;
case 8:
- O_R == 'O' ? add_08O(sub_tree,tmp_tvb) : add_08R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_08O(sub_tree,tmp_tvb) : add_08R(sub_tree,tmp_tvb, tap_rec);
break;
case 9:
- O_R == 'O' ? add_09O(sub_tree,tmp_tvb) : add_09R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_09O(sub_tree,tmp_tvb) : add_09R(sub_tree,tmp_tvb, tap_rec);
break;
case 10:
- O_R == 'O' ? add_10O(sub_tree,tmp_tvb) : add_10R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_10O(sub_tree,tmp_tvb) : add_10R(sub_tree,tmp_tvb, tap_rec);
break;
case 11:
- O_R == 'O' ? add_11O(sub_tree,tmp_tvb) : add_11R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_11O(sub_tree,tmp_tvb) : add_11R(sub_tree,tmp_tvb, tap_rec);
break;
case 12:
- O_R == 'O' ? add_12O(sub_tree,tmp_tvb) : add_12R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_12O(sub_tree,tmp_tvb) : add_12R(sub_tree,tmp_tvb, tap_rec);
break;
case 13:
- O_R == 'O' ? add_13O(sub_tree,tmp_tvb) : add_13R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_13O(sub_tree,tmp_tvb) : add_13R(sub_tree,tmp_tvb, tap_rec);
break;
case 14:
- O_R == 'O' ? add_14O(sub_tree,tmp_tvb) : add_14R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_14O(sub_tree,tmp_tvb) : add_14R(sub_tree,tmp_tvb, tap_rec);
break;
case 15:
- O_R == 'O' ? add_15O(sub_tree,tmp_tvb) : add_15R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_15O(sub_tree,tmp_tvb) : add_15R(sub_tree,tmp_tvb, tap_rec);
break;
case 16:
- O_R == 'O' ? add_16O(sub_tree,tmp_tvb) : add_16R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_16O(sub_tree,tmp_tvb) : add_16R(sub_tree,tmp_tvb, tap_rec);
break;
case 17:
- O_R == 'O' ? add_17O(sub_tree,tmp_tvb) : add_17R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_17O(sub_tree,tmp_tvb) : add_17R(sub_tree,tmp_tvb, tap_rec);
break;
case 18:
- O_R == 'O' ? add_18O(sub_tree,tmp_tvb) : add_18R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_18O(sub_tree,tmp_tvb) : add_18R(sub_tree,tmp_tvb, tap_rec);
break;
case 19:
- O_R == 'O' ? add_19O(sub_tree,tmp_tvb) : add_19R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_19O(sub_tree,tmp_tvb) : add_19R(sub_tree,tmp_tvb, tap_rec);
break;
case 20:
- O_R == 'O' ? add_20O(sub_tree,tmp_tvb) : add_20R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_20O(sub_tree,tmp_tvb) : add_20R(sub_tree,tmp_tvb, tap_rec);
break;
case 21:
- O_R == 'O' ? add_21O(sub_tree,tmp_tvb) : add_21R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_21O(sub_tree,tmp_tvb) : add_21R(sub_tree,tmp_tvb, tap_rec);
break;
case 22:
- O_R == 'O' ? add_22O(sub_tree,tmp_tvb) : add_22R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_22O(sub_tree,tmp_tvb) : add_22R(sub_tree,tmp_tvb, tap_rec);
break;
case 23:
- O_R == 'O' ? add_23O(sub_tree,tmp_tvb) : add_23R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_23O(sub_tree,tmp_tvb) : add_23R(sub_tree,tmp_tvb, tap_rec);
break;
case 24:
- O_R == 'O' ? add_24O(sub_tree,tmp_tvb) : add_24R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_24O(sub_tree,tmp_tvb) : add_24R(sub_tree,tmp_tvb, tap_rec);
break;
case 30:
- O_R == 'O' ? add_30O(sub_tree,tmp_tvb) : add_30R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_30O(sub_tree,tmp_tvb) : add_30R(sub_tree,tmp_tvb, tap_rec);
break;
case 31:
- O_R == 'O' ? add_31O(sub_tree,tmp_tvb) : add_31R(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_31O(sub_tree,tmp_tvb) : add_31R(sub_tree,tmp_tvb, tap_rec);
break;
case 51: case 52: case 53: case 54: case 55: case 56: case 57:
case 58:
- O_R == 'O' ? add_5xO(sub_tree,tmp_tvb) : add_5xR(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_5xO(sub_tree,tmp_tvb) : add_5xR(sub_tree,tmp_tvb, tap_rec);
break;
case 60: case 61:
- O_R == 'O' ? add_6xO(sub_tree,tmp_tvb,OT) : add_6xR(sub_tree,tmp_tvb);
+ O_R == 'O' ? add_6xO(sub_tree,tmp_tvb,OT) : add_6xR(sub_tree,tmp_tvb, tap_rec);
break;
default:
break;
}
}
+
+ /* Queue packet for Tap */
+ tap_queue_packet(ucp_tap, pinfo, tap_rec);
+
return;
}
-/* Register the protocol with Ethereal */
+/* Register the protocol with Wireshark */
void
proto_register_ucp(void)
{
},
{ &hf_ucp_oper_section,
{ "Data", "ucp.parm",
- FT_NONE, BASE_DEC, NULL, 0x00,
+ FT_NONE, BASE_NONE, NULL, 0x00,
"The actual content of the operation.",
HFILL
}
{ &hf_ucp_parm_LRR,
{ "LRR", "ucp.parm.LRR",
FT_UINT8, BASE_DEC, VALS(vals_parm_LRR), 0x00,
- "Leg. code for repitition flag.",
+ "Leg. code for repetition flag.",
HFILL
}
},
{ &hf_ucp_parm_RP,
{ "RP", "ucp.parm.RP",
FT_UINT8, BASE_DEC, VALS(vals_parm_RP), 0x00,
- "Repitition requested.",
+ "Repetition requested.",
HFILL
}
},
{ &hf_ucp_parm_LRP,
{ "LRP", "ucp.parm.LRP",
- FT_STRING, BASE_DEC, NULL, 0x00,
- "Legitimisation code for repitition.",
+ FT_STRING, BASE_NONE, NULL, 0x00,
+ "Legitimisation code for repetition.",
HFILL
}
},
},
{ &hf_ucp_parm_LPR,
{ "LPR", "ucp.parm.LPR",
- FT_STRING, BASE_DEC, NULL, 0x00,
+ FT_STRING, BASE_NONE, NULL, 0x00,
"Legitimisation code for priority requested.",
HFILL
}
},
{ &hf_ucp_parm_LUM,
{ "LUM", "ucp.parm.LUM",
- FT_STRING, BASE_DEC, NULL, 0x00,
+ FT_STRING, BASE_NONE, NULL, 0x00,
"Legitimisation code for urgent message.",
HFILL
}
},
{ &hf_ucp_parm_LRC,
{ "LRC", "ucp.parm.LRC",
- FT_STRING, BASE_DEC, NULL, 0x00,
+ FT_STRING, BASE_NONE, NULL, 0x00,
"Legitimisation code for reverse charging.",
HFILL
}
},
{ &hf_ucp_parm_CT,
{ "CT", "ucp.parm.CT",
- FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
"Accumulated charges timestamp.",
HFILL
}
},
{ &hf_ucp_parm_DDT,
{ "DDT", "ucp.parm.DDT",
- FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
"Deferred delivery time.",
HFILL
}
},
{ &hf_ucp_parm_ST,
{ "ST", "ucp.parm.ST",
- FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
"Start time.",
HFILL
}
},
{ &hf_ucp_parm_SP,
{ "SP", "ucp.parm.SP",
- FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
"Stop time.",
HFILL
}
},
{ &hf_ucp_parm_VP,
{ "VP", "ucp.parm.VP",
- FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
"Validity period.",
HFILL
}
},
{ &hf_ucp_parm_SCTS,
{ "SCTS", "ucp.parm.SCTS",
- FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
"Service Centre timestamp.",
HFILL
}
},
{ &hf_ucp_parm_DSCTS,
{ "DSCTS", "ucp.parm.DSCTS",
- FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
"Delivery timestamp.",
HFILL
}
}
},
{ &hf_ucp_parm_NB,
- { " NB", "ucp.parm.NB",
+ { "NB", "ucp.parm.NB",
FT_STRING, BASE_NONE, NULL, 0x00,
"No. of bits in Transparent Data (TD) message.",
HFILL
}
},
{ &hf_ucp_data_section,
- { " Data", "ucp.message",
+ { "Data", "ucp.message",
FT_NONE, BASE_NONE, NULL, 0x00,
"The actual message or data.",
HFILL
},
{ &hf_ucp_parm_XSer,
{ "Extra services:", "ucp.parm.XSer",
- FT_NONE, BASE_DEC, NULL, 0x00,
+ FT_NONE, BASE_NONE, NULL, 0x00,
"Extra services.",
HFILL
}
},
{ &hf_ucp_parm_MVP,
{ "MVP", "ucp.parm.MVP",
- FT_ABSOLUTE_TIME, BASE_NONE, NULL, 0x00,
- "Mofified validity period.",
+ FT_ABSOLUTE_TIME, ABSOLUTE_TIME_LOCAL, NULL, 0x00,
+ "Modified validity period.",
HFILL
}
},
&ett_sub,
&ett_XSer
};
- /* Register the protocol name and description */
+ module_t *ucp_module;
+
+ /* Register the protocol name and description */
proto_ucp = proto_register_protocol("Universal Computer Protocol",
"UCP", "ucp");
/* Required function calls to register header fields and subtrees used */
proto_register_field_array(proto_ucp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+
+ /* Register for tapping */
+ ucp_tap = register_tap("ucp");
+
+ /* register preferences */
+ ucp_module = prefs_register_protocol(proto_ucp, NULL);
+ prefs_register_bool_preference(ucp_module, "desegment_ucp_messages",
+ "Reassemble UCP messages spanning multiple TCP segments",
+ "Whether the UCP dissector should reassemble messages spanning multiple TCP segments."
+ " To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" in the TCP protocol settings.",
+ &ucp_desegment);
+
}
/*
/*
* Also register as one that can be selected by a TCP port number.
*/
- ucp_handle = create_dissector_handle(dissect_ucp, proto_ucp);
+ ucp_handle = create_dissector_handle(dissect_ucp_tcp, proto_ucp);
dissector_add_handle("tcp.port", ucp_handle);
+
+ /* Tapping setup */
+ stats_tree_register_with_group("ucp", "ucp_messages", "_UCP Messages", 0,
+ ucp_stats_tree_per_packet, ucp_stats_tree_init,
+ NULL, REGISTER_STAT_GROUP_TELEPHONY);
}