* 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.
/* Initialize the subtree pointers */
static gint ett_ucp = -1;
+static gint ett_sub = -1;
static gint ett_XSer = -1;
/*
* \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)
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);
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
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);
#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);
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
*/
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
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);
/*
* 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 */
},
{ &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
}
/* Setup protocol subtree array */
static gint *ett[] = {
&ett_ucp,
+ &ett_sub,
&ett_XSer
};
/* Register the protocol name and description */
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);
}