diff options
author | Bill Meier <wmeier@newsguy.com> | 2010-05-03 23:05:27 +0000 |
---|---|---|
committer | Bill Meier <wmeier@newsguy.com> | 2010-05-03 23:05:27 +0000 |
commit | 3bf735ba4946d5a4149bbd7d03e1152797820e3c (patch) | |
tree | 86ae0611d816333710891f3c852ae9eac068425e /epan | |
parent | 93a82410e35d1a440c2f9e908ee174cd04c67ec0 (diff) |
Rework code to handle multiple messages in a packet.
Fixes Bug #4709.
See: https://bugs.wireshark.org/bugzilla/show_bug.cgi?id=4709
svn path=/trunk/; revision=32654
Diffstat (limited to 'epan')
-rw-r--r-- | epan/dissectors/packet-ucp.c | 358 |
1 files changed, 180 insertions, 178 deletions
diff --git a/epan/dissectors/packet-ucp.c b/epan/dissectors/packet-ucp.c index dee5f11d0b..1ff6be99e5 100644 --- a/epan/dissectors/packet-ucp.c +++ b/epan/dissectors/packet-ucp.c @@ -47,11 +47,13 @@ #include <epan/packet.h> #include <epan/prefs.h> #include <epan/emem.h> +#include <epan/conversation.h> #include <epan/stats_tree.h> #include "packet-tcp.h" /* Prototypes */ +static void dissect_ucp_tcp(tvbuff_t *, packet_info *, proto_tree *); static void dissect_ucp_common(tvbuff_t *, packet_info *, proto_tree *); /* Tap Record */ @@ -63,8 +65,8 @@ typedef struct _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 +/* STX + TRN(2 num. char.) + / + LEN(5 num. char.) + / + 'O'/'R' + / + OT(2 num. char.) + / */ +#define UCP_HEADER_SIZE 15 /* * Convert ASCII-hex character to binary equivalent. No checks, assume @@ -72,20 +74,24 @@ gboolean ucp_desegment = TRUE; */ #define AHex2Bin(n) (((n) & 0x40) ? ((n) & 0x0F) + 9 : ((n) & 0x0F)) -#define UCP_STX 0x02 /* Start of UCP PDU */ -#define UCP_ETX 0x03 /* End of UCP PDU */ +#define UCP_STX 0x02 /* Start of UCP PDU */ +#define UCP_ETX 0x03 /* End of UCP PDU */ -#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_MALFORMED -1 /* Not a valid PDU */ +#define UCP_INV_CHK -2 /* Incorrect checksum */ -#define UCP_O_R_OFFSET 10 /* Location of O/R field*/ -#define UCP_OT_OFFSET 12 /* Location of OT field */ +#define UCP_TRN_OFFSET 1 +#define UCP_LEN_OFFSET 4 +#define UCP_O_R_OFFSET 10 /* Location of O/R field */ +#define UCP_OT_OFFSET 12 /* Location of OT field */ -#define UCP_TRN_LEN 2 /* Length of TRN-field */ -#define UCP_LEN_LEN 5 /* Length of LEN-field */ -#define UCP_O_R_LEN 1 /* Length of O/R-field */ -#define UCP_OT_LEN 2 /* Length of OT-field */ +#define UCP_TRN_LEN 2 /* Length of TRN-field */ +#define UCP_LEN_LEN 5 /* Length of LEN-field */ +#define UCP_O_R_LEN 1 /* Length of O/R-field */ +#define UCP_OT_LEN 2 /* Length of OT-field */ + + +static dissector_handle_t ucp_handle; /* * Initialize the protocol and registered fields @@ -102,134 +108,134 @@ 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"; +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 int hf_ucp_oper_section = -1; -static int hf_ucp_parm_AdC = -1; -static int hf_ucp_parm_OAdC = -1; -static int hf_ucp_parm_DAdC = -1; -static int hf_ucp_parm_AC = -1; -static int hf_ucp_parm_OAC = -1; -static int hf_ucp_parm_BAS = -1; -static int hf_ucp_parm_LAR = -1; -static int hf_ucp_parm_LAC = -1; -static int hf_ucp_parm_L1R = -1; -static int hf_ucp_parm_L1P = -1; -static int hf_ucp_parm_L3R = -1; -static int hf_ucp_parm_L3P = -1; -static int hf_ucp_parm_LCR = -1; -static int hf_ucp_parm_LUR = -1; -static int hf_ucp_parm_LRR = -1; -static int hf_ucp_parm_RT = -1; -static int hf_ucp_parm_NoN = -1; -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; -static int hf_ucp_parm_CS = -1; -static int hf_ucp_parm_PID = -1; -static int hf_ucp_parm_NPL = -1; -static int hf_ucp_parm_GA = -1; -static int hf_ucp_parm_RP = -1; -static int hf_ucp_parm_LRP = -1; -static int hf_ucp_parm_PR = -1; -static int hf_ucp_parm_LPR = -1; -static int hf_ucp_parm_UM = -1; -static int hf_ucp_parm_LUM = -1; -static int hf_ucp_parm_RC = -1; -static int hf_ucp_parm_LRC = -1; -static int hf_ucp_parm_NRq = -1; -static int hf_ucp_parm_GAdC = -1; -static int hf_ucp_parm_A_D = -1; -static int hf_ucp_parm_CT = -1; -static int hf_ucp_parm_AAC = -1; -static int hf_ucp_parm_MNo = -1; -static int hf_ucp_parm_R_T = -1; -static int hf_ucp_parm_IVR5x = -1; -static int hf_ucp_parm_REQ_OT = -1; -static int hf_ucp_parm_SSTAT = -1; -static int hf_ucp_parm_LMN = -1; -static int hf_ucp_parm_NMESS = -1; -static int hf_ucp_parm_NMESS_str= -1; -static int hf_ucp_parm_NAdC = -1; -static int hf_ucp_parm_NT = -1; -static int hf_ucp_parm_NPID = -1; -static int hf_ucp_parm_LRq = -1; -static int hf_ucp_parm_LRAd = -1; -static int hf_ucp_parm_LPID = -1; -static int hf_ucp_parm_DD = -1; -static int hf_ucp_parm_DDT = -1; -static int hf_ucp_parm_STx = -1; -static int hf_ucp_parm_ST = -1; -static int hf_ucp_parm_SP = -1; -static int hf_ucp_parm_VP = -1; -static int hf_ucp_parm_RPID = -1; -static int hf_ucp_parm_SCTS = -1; -static int hf_ucp_parm_Dst = -1; -static int hf_ucp_parm_Rsn = -1; -static int hf_ucp_parm_DSCTS = -1; -static int hf_ucp_parm_MT = -1; -static int hf_ucp_parm_NB = -1; -static int hf_ucp_data_section = -1; -static int hf_ucp_parm_MMS = -1; -static int hf_ucp_parm_DCs = -1; -static int hf_ucp_parm_MCLs = -1; -static int hf_ucp_parm_RPI = -1; -static int hf_ucp_parm_CPg = -1; -static int hf_ucp_parm_RPLy = -1; -static int hf_ucp_parm_OTOA = -1; -static int hf_ucp_parm_HPLMN = -1; -static int hf_ucp_parm_RES4 = -1; -static int hf_ucp_parm_RES5 = -1; -static int hf_ucp_parm_OTON = -1; -static int hf_ucp_parm_ONPI = -1; -static int hf_ucp_parm_STYP0 = -1; -static int hf_ucp_parm_STYP1 = -1; -static int hf_ucp_parm_ACK = -1; -static int hf_ucp_parm_PWD = -1; -static int hf_ucp_parm_NPWD = -1; -static int hf_ucp_parm_VERS = -1; -static int hf_ucp_parm_LAdC = -1; -static int hf_ucp_parm_LTON = -1; -static int hf_ucp_parm_LNPI = -1; -static int hf_ucp_parm_OPID = -1; -static int hf_ucp_parm_RES1 = -1; -static int hf_ucp_parm_RES2 = -1; -static int hf_ucp_parm_MVP = -1; -static int hf_ucp_parm_EC = -1; -static int hf_ucp_parm_SM = -1; - -static int hf_ucp_parm_XSer = -1; -static int hf_xser_service = -1; -static int hf_xser_length = -1; -static int hf_xser_data = -1; +static int hf_ucp_oper_section = -1; +static int hf_ucp_parm_AdC = -1; +static int hf_ucp_parm_OAdC = -1; +static int hf_ucp_parm_DAdC = -1; +static int hf_ucp_parm_AC = -1; +static int hf_ucp_parm_OAC = -1; +static int hf_ucp_parm_BAS = -1; +static int hf_ucp_parm_LAR = -1; +static int hf_ucp_parm_LAC = -1; +static int hf_ucp_parm_L1R = -1; +static int hf_ucp_parm_L1P = -1; +static int hf_ucp_parm_L3R = -1; +static int hf_ucp_parm_L3P = -1; +static int hf_ucp_parm_LCR = -1; +static int hf_ucp_parm_LUR = -1; +static int hf_ucp_parm_LRR = -1; +static int hf_ucp_parm_RT = -1; +static int hf_ucp_parm_NoN = -1; +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; +static int hf_ucp_parm_CS = -1; +static int hf_ucp_parm_PID = -1; +static int hf_ucp_parm_NPL = -1; +static int hf_ucp_parm_GA = -1; +static int hf_ucp_parm_RP = -1; +static int hf_ucp_parm_LRP = -1; +static int hf_ucp_parm_PR = -1; +static int hf_ucp_parm_LPR = -1; +static int hf_ucp_parm_UM = -1; +static int hf_ucp_parm_LUM = -1; +static int hf_ucp_parm_RC = -1; +static int hf_ucp_parm_LRC = -1; +static int hf_ucp_parm_NRq = -1; +static int hf_ucp_parm_GAdC = -1; +static int hf_ucp_parm_A_D = -1; +static int hf_ucp_parm_CT = -1; +static int hf_ucp_parm_AAC = -1; +static int hf_ucp_parm_MNo = -1; +static int hf_ucp_parm_R_T = -1; +static int hf_ucp_parm_IVR5x = -1; +static int hf_ucp_parm_REQ_OT = -1; +static int hf_ucp_parm_SSTAT = -1; +static int hf_ucp_parm_LMN = -1; +static int hf_ucp_parm_NMESS = -1; +static int hf_ucp_parm_NMESS_str = -1; +static int hf_ucp_parm_NAdC = -1; +static int hf_ucp_parm_NT = -1; +static int hf_ucp_parm_NPID = -1; +static int hf_ucp_parm_LRq = -1; +static int hf_ucp_parm_LRAd = -1; +static int hf_ucp_parm_LPID = -1; +static int hf_ucp_parm_DD = -1; +static int hf_ucp_parm_DDT = -1; +static int hf_ucp_parm_STx = -1; +static int hf_ucp_parm_ST = -1; +static int hf_ucp_parm_SP = -1; +static int hf_ucp_parm_VP = -1; +static int hf_ucp_parm_RPID = -1; +static int hf_ucp_parm_SCTS = -1; +static int hf_ucp_parm_Dst = -1; +static int hf_ucp_parm_Rsn = -1; +static int hf_ucp_parm_DSCTS = -1; +static int hf_ucp_parm_MT = -1; +static int hf_ucp_parm_NB = -1; +static int hf_ucp_data_section = -1; +static int hf_ucp_parm_MMS = -1; +static int hf_ucp_parm_DCs = -1; +static int hf_ucp_parm_MCLs = -1; +static int hf_ucp_parm_RPI = -1; +static int hf_ucp_parm_CPg = -1; +static int hf_ucp_parm_RPLy = -1; +static int hf_ucp_parm_OTOA = -1; +static int hf_ucp_parm_HPLMN = -1; +static int hf_ucp_parm_RES4 = -1; +static int hf_ucp_parm_RES5 = -1; +static int hf_ucp_parm_OTON = -1; +static int hf_ucp_parm_ONPI = -1; +static int hf_ucp_parm_STYP0 = -1; +static int hf_ucp_parm_STYP1 = -1; +static int hf_ucp_parm_ACK = -1; +static int hf_ucp_parm_PWD = -1; +static int hf_ucp_parm_NPWD = -1; +static int hf_ucp_parm_VERS = -1; +static int hf_ucp_parm_LAdC = -1; +static int hf_ucp_parm_LTON = -1; +static int hf_ucp_parm_LNPI = -1; +static int hf_ucp_parm_OPID = -1; +static int hf_ucp_parm_RES1 = -1; +static int hf_ucp_parm_RES2 = -1; +static int hf_ucp_parm_MVP = -1; +static int hf_ucp_parm_EC = -1; +static int hf_ucp_parm_SM = -1; + +static int hf_ucp_parm_XSer = -1; +static int hf_xser_service = -1; +static int hf_xser_length = -1; +static int hf_xser_data = -1; /* Initialize the subtree pointers */ -static gint ett_ucp = -1; -static gint ett_sub = -1; -static gint ett_XSer = -1; +static gint ett_ucp = -1; +static gint ett_sub = -1; +static gint ett_XSer = -1; /* Tap */ -static int ucp_tap = -1; +static int ucp_tap = -1; /* * Value-arrays for certain field-contents @@ -701,13 +707,15 @@ ucp_stats_tree_per_packet(stats_tree *st, /* st as it was passed to us */ /*! * Checks whether the PDU looks a bit like UCP and checks the checksum * + * Note: check_ucp is called only with a buffer of at least LEN+2 bytes. + * IOW: The buffer should contain a complete UCP PDU [STX ... ETX] + * * \param tvb The buffer with PDU-data * \param endpkt Returns pointer, indicating the end of the PDU * * \return The state of this PDU * \retval 0 Definitely UCP - * \retval UCP_SHORTENED Packet may be there, but not complete - * \retval UCP_MALFORMED Hmmmm, not UCP after all... + * \retval UCP_MALFORMED ??? * \retval UCP_INV_CHK Nice packet, but checksum doesn't add up... */ static int @@ -721,11 +729,6 @@ check_ucp(tvbuff_t *tvb, int *endpkt) length = tvb_find_guint8(tvb, offset, -1, UCP_ETX); if (length == -1) { *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; } for (; offset < (guint) (length - 2); offset++) @@ -1695,46 +1698,49 @@ add_6xO(proto_tree *tree, tvbuff_t *tvb, guint8 OT) #undef UcpHandleTime #undef UcpHandleData -/* Code to actually dissect the packets */ -/* - * Overlapping data for these functions - */ -static int result, endpkt; - /* * The heuristic dissector */ + static gboolean dissect_ucp_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { - guint8 O_R; /* Request or response */ + conversation_t *conversation; - /* 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; + /* Heuristic */ - result = check_ucp(tvb, &endpkt); + if (tvb_length(tvb) < UCP_HEADER_SIZE) + return FALSE; - if (result == UCP_MALFORMED) + if ((tvb_get_guint8(tvb, 0) != UCP_STX) || + (tvb_get_guint8(tvb, UCP_TRN_OFFSET + UCP_TRN_LEN) != '/') || + (tvb_get_guint8(tvb, UCP_LEN_OFFSET + UCP_LEN_LEN) != '/') || + (tvb_get_guint8(tvb, UCP_O_R_OFFSET + UCP_O_R_LEN) != '/') || + (tvb_get_guint8(tvb, UCP_OT_OFFSET + UCP_OT_LEN) != '/')) return FALSE; - if (endpkt < UCP_OT_OFFSET + 1) - /* - * Might be shortened packet but don't handle anyway. - */ + + if (match_strval(tvb_get_guint8(tvb, UCP_O_R_OFFSET), vals_hdr_O_R) == NULL) return FALSE; /* - * Try getting the operation-type and whether it's a request/response + * Ok, looks like a valid packet */ - 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. + + /* Set up a conversation with attached dissector so dissect_ucp_heur + * won't be called any more for this TCP connection. */ - dissect_ucp_common(tvb, pinfo, tree); + conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst, + pinfo->ptype, pinfo->srcport, pinfo->destport, 0); + if (conversation == NULL) + { + conversation = conversation_new(pinfo->fd->num, &pinfo->src, &pinfo->dst, + pinfo->ptype, pinfo->srcport, pinfo->destport, 0); + } + conversation_set_dissector(conversation, ucp_handle); + + dissect_ucp_tcp(tvb, pinfo, tree); + return TRUE; } @@ -1764,6 +1770,9 @@ dissect_ucp_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) /* * The actual dissector */ + +/* We get here only with at least LEN+2 bytes in the buffer */ + static void dissect_ucp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { @@ -1772,6 +1781,8 @@ dissect_ucp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) guint8 OT; /* Operation type */ guint intval; int i; + int result; + int endpkt; ucp_tap_rec_t* tap_rec; /* Tap record */ /* Set up structures needed to add the protocol subtree and manage it */ @@ -1785,8 +1796,6 @@ dissect_ucp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) col_set_str(pinfo->cinfo, COL_PROTOCOL, "UCP"); col_clear(pinfo->cinfo, COL_INFO); - /* 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; @@ -1808,14 +1817,11 @@ dissect_ucp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) 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_append_fstr(pinfo->cinfo, COL_INFO, "%s (%s)", val_to_str(OT, vals_hdr_OT, "unknown operation"), 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_INV_CHK) col_append_str(pinfo->cinfo, COL_INFO, " [checksum invalid]"); } @@ -1857,10 +1863,8 @@ dissect_ucp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) offset += UCP_OT_LEN; /* - * Variable part starts here. Don't dissect if not complete. + * Variable part starts here. */ - if (result == UCP_SHORTENED) - return; tmp_tvb = tvb_new_subset_remaining(tvb, offset); sub_ti = proto_tree_add_item(ucp_tree, hf_ucp_oper_section, tvb, @@ -2752,16 +2756,14 @@ proto_register_ucp(void) 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. + * UCP can be spoken on any port so, when not on a specific port, try heuristic + * whenever TCP is spoken. */ heur_dissector_add("tcp", dissect_ucp_heur, proto_ucp); /* - * Also register as one that can be selected by a TCP port number. + * Also register as a dissectoir that can be selected by a TCP port number via "decode as". */ ucp_handle = create_dissector_handle(dissect_ucp_tcp, proto_ucp); dissector_add_handle("tcp.port", ucp_handle); |