diff options
author | Luis Ontanon <luis.ontanon@gmail.com> | 2005-11-01 16:28:13 +0000 |
---|---|---|
committer | Luis Ontanon <luis.ontanon@gmail.com> | 2005-11-01 16:28:13 +0000 |
commit | f100a332165a49e6f086f60130a8bb6c427024ce (patch) | |
tree | 7c031183762312bab7e5a72252f72852c9d06764 /asn1/h248 | |
parent | aa01054c6aea6fda157338f1b49c9e5c878bd30a (diff) |
- Embryonic Transaction & Context tracing
svn path=/trunk/; revision=16372
Diffstat (limited to 'asn1/h248')
-rw-r--r-- | asn1/h248/h248.cnf | 108 | ||||
-rw-r--r-- | asn1/h248/packet-h248-template.c | 753 | ||||
-rw-r--r-- | asn1/h248/packet-h248-template.h | 77 |
3 files changed, 809 insertions, 129 deletions
diff --git a/asn1/h248/h248.cnf b/asn1/h248/h248.cnf index 614c2bd009..fede98391e 100644 --- a/asn1/h248/h248.cnf +++ b/asn1/h248/h248.cnf @@ -16,6 +16,7 @@ PropertyID SignalName EventName ContextID +ErrorCode #.TYPE_RENAME IndAudMediaDescriptor/streams indAudMediaDescriptorStreams @@ -75,20 +76,51 @@ ServiceChangeReply/terminationID terminationIDList offset = dissect_h248_trx_id(implicit_tag, pinfo, tree, tvb, offset); #.END -#.FN_BODY transactionReply/transactionId +#.FN_BODY TransactionReply/transactionId offset = dissect_h248_trx_id(implicit_tag, pinfo, tree, tvb, offset); #.END -#.FN_FTR TransactionRequest - if (check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, "} }"); +#.FN_BODY TransactionResponseAck/transactionId + offset = dissect_h248_trx_id(implicit_tag, pinfo, tree, tvb, offset); +#.END + +#.FN_HDR Command + h248_cmdmsg = ep_alloc0(sizeof(h248_cmdmsg_info_t)); + h248_cmdmsg->offset = offset; + h248_cmdmsg->transaction_id = transaction_id; + h248_cmdmsg->context_id = context_id; + h248_cmdmsg->cmd_type = H248_CMD_NONE; + h248_cmdmsg->msg_type = H248_TRX_REQUEST; + h248_cmdmsg->term_is_wildcard = FALSE; #.END -#.FN_FTR TransactionPending - if (check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, "} }"); +#.FN_FTR Command + if (check_col(pinfo->cinfo, COL_INFO)) col_set_str(pinfo->cinfo, COL_INFO, cmd_str(h248_cmdmsg)); + + if (keep_persistent_data) { + cmdmsg_tree(h248_cmdmsg); + analyze_h248_cmd(pinfo,h248_cmdmsg); + analysis_tree(pinfo, tvb, h248_tree, h248_cmdmsg); + } #.END -#.FN_FTR TransactionAck - if (check_col(pinfo->cinfo, COL_INFO)) col_append_str(pinfo->cinfo, COL_INFO, "} }"); +#.FN_HDR CommandReply + h248_cmdmsg = ep_alloc0(sizeof(h248_cmdmsg_info_t)); + h248_cmdmsg->offset = offset; + h248_cmdmsg->transaction_id = transaction_id; + h248_cmdmsg->context_id = context_id; + h248_cmdmsg->cmd_type = H248_CMD_NONE; + h248_cmdmsg->msg_type = H248_TRX_REPLY; + h248_cmdmsg->term_is_wildcard = FALSE; +#.END + +#.FN_FTR CommandReply + if (check_col(pinfo->cinfo, COL_INFO)) col_set_str(pinfo->cinfo, COL_INFO, cmd_str(h248_cmdmsg)); + if (keep_persistent_data) { + cmdmsg_tree(h248_cmdmsg); + analyze_h248_cmd(pinfo,h248_cmdmsg); + analysis_tree(pinfo, tvb, h248_tree, h248_cmdmsg); + } #.END #.FN_BODY ActionRequest/contextId @@ -100,90 +132,88 @@ ServiceChangeReply/terminationID terminationIDList #.END #.FN_HDR Command/addReq - command_string = "addReq {"; + h248_cmdmsg->cmd_type = H248_CMD_ADD; #.END #.FN_HDR Command/moveReq - command_string = "moveReq {"; + h248_cmdmsg->cmd_type = H248_CMD_MOVE; #.END #.FN_HDR Command/modReq - command_string = "modReq {"; + h248_cmdmsg->cmd_type = H248_CMD_MOD; #.END #.FN_HDR Command/subtractReq - command_string = "subtractReq {"; + h248_cmdmsg->cmd_type = H248_CMD_SUB; #.END #.FN_HDR Command/auditCapRequest - command_string = "auditCapRequest {"; + h248_cmdmsg->cmd_type = H248_CMD_AUDITCAP; #.END #.FN_HDR Command/auditValueRequest - command_string = "auditValueRequest {"; + h248_cmdmsg->cmd_type = H248_CMD_AUDITVAL; #.END #.FN_HDR Command/notifyReq - command_string = "notifyReq {"; + h248_cmdmsg->cmd_type = H248_CMD_NOTIFY; #.END #.FN_HDR Command/ServiceChangeRequest - command_string = "serviceChangeReq {"; + h248_cmdmsg->cmd_type = H248_CMD_SVCCHG; #.END #.FN_HDR CommandReply/addReply - command_string = "addReply {"; + h248_cmdmsg->cmd_type = H248_CMD_ADD; #.END #.FN_HDR CommandReply/moveReply - command_string = "moveReply {"; + h248_cmdmsg->cmd_type = H248_CMD_MOVE; #.END -#.FN_HDR CommandReply/addReply - command_string = "addReply {"; +#.FN_HDR CommandReply/modReply + h248_cmdmsg->cmd_type = H248_CMD_MOD; #.END -#.FN_HDR CommandReply/modReply - command_string = "modReply {"; +#.FN_HDR CommandReply/subtractReply + h248_cmdmsg->cmd_type = H248_CMD_SUB; #.END #.FN_HDR CommandReply/notifyReply - command_string = "notifyReply {"; + h248_cmdmsg->cmd_type = H248_CMD_NOTIFY; #.END -#.FN_HDR CommandReply/subtractReply - command_string = "subtractReply {"; +#.FN_HDR CommandReply/ServiceChangeReply + h248_cmdmsg->cmd_type = H248_CMD_SVCCHG; #.END #.FN_HDR CommandReply/auditCapReply - command_string = "auditCapReply {"; + h248_cmdmsg->cmd_type = H248_CMD_AUDITCAP; #.END #.FN_HDR CommandReply/auditValueReply - command_string = "auditValueReply {"; + h248_cmdmsg->cmd_type = H248_CMD_AUDITVAL; #.END -#.FN_HDR TerminationID - if (check_col(pinfo->cinfo, COL_INFO) && command_string != NULL ) col_append_str(pinfo->cinfo, COL_INFO, command_string); - it_is_wildcard = FALSE; -#.END - -#.FN_FTR TerminationID - if (check_col(pinfo->cinfo, COL_INFO) && command_string != NULL ) col_append_str(pinfo->cinfo, COL_INFO, "}"); - it_is_wildcard = FALSE; +#.FN_HDR WildcardField + h248_cmdmsg->term_is_wildcard = TRUE; #.END -#.FN_HDR WildcardField - if (check_col(pinfo->cinfo, COL_INFO) && command_string != NULL ) col_append_str(pinfo->cinfo, COL_INFO, "*"); - it_is_wildcard = TRUE; +#.FN_BODY ErrorDescriptor/errorCode + guint32 val; + + val = 0; + offset = dissect_ber_integer(implicit_tag, pinfo, tree, tvb, offset, hf_h248_error_code, &val); + h248_cmdmsg->error_code = val; + + return offset; #.END #.FN_BODY TerminationID/id tvbuff_t* new_tvb; offset = dissect_ber_octet_string(implicit_tag, pinfo, tree, tvb, offset, hf_index, &new_tvb); - if (command_string != NULL && ! it_is_wildcard && check_col(pinfo->cinfo, COL_INFO)) - col_append_str(pinfo->cinfo, COL_INFO, bytes_to_str(tvb_get_ptr(tvb,0,tvb->length),tvb->length)); + h248_cmdmsg->term_id = bytes_to_str(tvb_get_ptr(tvb,0,tvb->length),tvb->length); if (new_tvb && h248_term_handle) { call_dissector(h248_term_handle, new_tvb, pinfo, tree); diff --git a/asn1/h248/packet-h248-template.c b/asn1/h248/packet-h248-template.c index 66fb12df4f..d744c77b15 100644 --- a/asn1/h248/packet-h248-template.c +++ b/asn1/h248/packet-h248-template.c @@ -31,14 +31,17 @@ #include <epan/packet.h> #include <epan/conversation.h> #include <epan/strutil.h> +#include <epan/emem.h> +#include <epan/expert.h> +#include <epan/prefs.h> #include <stdio.h> #include <string.h> -#include "packet-ber.h" +#include <epan/dissectors/packet-ber.h> #include "packet-h248.h" -#include "packet-isup.h" -#include "packet-q931.h" +#include <epan/dissectors/packet-isup.h> +#include <epan/dissectors/packet-q931.h> #include <epan/sctpppids.h> #define PNAME "H.248 MEGACO" @@ -69,8 +72,25 @@ static int hf_h248_package_3GUP_UPversions = -1; static int hf_h248_package_3GUP_delerrsdu = -1; static int hf_h248_package_3GUP_interface = -1; static int hf_h248_package_3GUP_initdir = -1; -static int hf_h248_contextId_64 = -1; -static int hf_h248_transactionId_64 = -1; +static int hf_h248_context_id = -1; +static int hf_h248_error_code = -1; + +static int hf_h248_cmd_trx = -1; +static int hf_h248_cmd_request = -1; +static int hf_h248_cmd_reply = -1; +static int hf_h248_cmd_dup_request = -1; +static int hf_h248_cmd_dup_reply = -1; +static int hf_h248_cmd_start = -1; +static int hf_h248_cmd_error = -1; +static int hf_h248_cmd_ctx = -1; +static int hf_h248_ctx_start = -1; +static int hf_h248_ctx_last = -1; +static int hf_h248_ctx_cmd = -1; +static int hf_h248_ctx_cmd_type = -1; +static int hf_h248_ctx_cmd_request = -1; +static int hf_h248_ctx_cmd_reply = -1; +static int hf_h248_ctx_cmd_error = -1; + #include "packet-h248-hf.c" @@ -80,14 +100,40 @@ static gint ett_mtpaddress = -1; static gint ett_packagename = -1; static gint ett_codec = -1; -#include "packet-h248-ett.c" -static const gchar* command_string; -static gboolean it_is_wildcard; +static gint ett_cmd = -1; +static gint ett_ctx = -1; +static gint ett_ctx_cmd = -1; +static gint ett_ctx_cmds = -1; +static gint ett_debug = -1; + +#include "packet-h248-ett.c" static dissector_handle_t h248_term_handle; +#if 0 +static GHashTable* h248_package_signals = NULL; +static GHashTable* h248_package_events = NULL; +static GHashTable* h248_package_properties = NULL; + static dissector_table_t h248_package_bin_dissector_table=NULL; +#endif + +static GHashTable* transactions = NULL; +static GHashTable* transactions_by_framenum = NULL; +static GHashTable* contexts_creating = NULL; +static GHashTable* contexts = NULL; + +static gboolean keep_persistent_data = FALSE; + +static h248_cmdmsg_info_t* h248_cmdmsg; +static guint32 transaction_id; +static guint32 context_id; + +static proto_tree *h248_tree; + +static dissector_handle_t h248_term_handle; + static const value_string package_name_vals[] = { { 0x0000, "Media stream properties H.248.1 Annex C" }, @@ -290,15 +336,141 @@ static const true_false_string h248_tdmc_ec_vals = { }; + + +#define NULL_CONTEXT 0 +#define CHOOSE_CONTEXT 0xFFFFFFFE +#define ALL_CONTEXTS 0xFFFFFFFF + #if 0 static const value_string context_id_type[] = { - {0x00000000,"0 (Null Context)"}, - {0xFFFFFFFE,"$ (Choose Context)"}, - {0xFFFFFFFF,"* (All Contexts)"}, + {NULL_CONTEXT,"0 (Null Context)"}, + {CHOOSE_CONTEXT,"$ (Choose Context)"}, + {ALL_CONTEXTS,"* (All Contexts)"}, {0,NULL} }; #endif +static const value_string h248_reasons[] = { + { 400, "Syntax error in message"}, + { 401, "Protocol Error"}, + { 402, "Unauthorized"}, + { 403, "Syntax error in transaction request"}, + { 406, "Version Not Supported"}, + { 410, "Incorrect identifier"}, + { 411, "The transaction refers to an unknown ContextId"}, + { 412, "No ContextIDs available"}, + { 421, "Unknown action or illegal combination of actions"}, + { 422, "Syntax Error in Action"}, + { 430, "Unknown TerminationID"}, + { 431, "No TerminationID matched a wildcard"}, + { 432, "Out of TerminationIDs or No TerminationID available"}, + { 433, "TerminationID is already in a Context"}, + { 434, "Max number of Terminations in a Context exceeded"}, + { 435, "Termination ID is not in specified Context"}, + { 440, "Unsupported or unknown Package"}, + { 441, "Missing Remote or Local Descriptor"}, + { 442, "Syntax Error in Command"}, + { 443, "Unsupported or Unknown Command"}, + { 444, "Unsupported or Unknown Descriptor"}, + { 445, "Unsupported or Unknown Property"}, + { 446, "Unsupported or Unknown Parameter"}, + { 447, "Descriptor not legal in this command"}, + { 448, "Descriptor appears twice in a command"}, + { 449, "Unsupported or Unknown Parameter or Property Value"}, + { 450, "No such property in this package"}, + { 451, "No such event in this package"}, + { 452, "No such signal in this package"}, + { 453, "No such statistic in this package"}, + { 454, "No such parameter value in this package"}, + { 455, "Property illegal in this Descriptor"}, + { 456, "Property appears twice in this Descriptor"}, + { 457, "Missing parameter in signal or event"}, + { 458, "Unexpected Event/Request ID"}, + { 459, "Unsupported or Unknown Profile"}, + { 460, "Unable to set statistic on stream"}, + { 471, "Implied Add for Multiplex failure"}, + { 500, "Internal software Failure in MG"}, + { 501, "Not Implemented"}, + { 502, "Not ready"}, + { 503, "Service Unavailable"}, + { 504, "Command Received from unauthorized entity"}, + { 505, "Transaction Request Received before a Service Change Reply has been received"}, + { 506, "Number of Transaction Pendings Exceeded"}, + { 510, "Insufficient resources"}, + { 512, "Media Gateway unequipped to detect requested Event"}, + { 513, "Media Gateway unequipped to generate requested Signals"}, + { 514, "Media Gateway cannot send the specified announcement"}, + { 515, "Unsupported Media Type"}, + { 517, "Unsupported or invalid mode"}, + { 518, "Event buffer full"}, + { 519, "Out of space to store digit map"}, + { 520, "Digit Map undefined in the MG"}, + { 521, "Termination is ServiceChangeing"}, + { 522, "Functionality Requested in Topology Triple Not Supported"}, + { 526, "Insufficient bandwidth"}, + { 529, "Internal hardware failure in MG"}, + { 530, "Temporary Network failure"}, + { 531, "Permanent Network failure"}, + { 532, "Audited Property, Statistic, Event or Signal does not exist"}, + { 533, "Response exceeds maximum transport PDU size"}, + { 534, "Illegal write or read only property"}, + { 540, "Unexpected initial hook state"}, + { 542, "Command is not allowed on this termination"}, + { 581, "Does Not Exist"}, + { 600, "Illegal syntax within an announcement specification"}, + { 601, "Variable type not supported"}, + { 602, "Variable value out of range"}, + { 603, "Category not supported"}, + { 604, "Selector type not supported"}, + { 605, "Selector value not supported"}, + { 606, "Unknown segment ID"}, + { 607, "Mismatch between play specification and provisioned data"}, + { 608, "Provisioning error"}, + { 609, "Invalid offset"}, + { 610, "No free segment IDs"}, + { 611, "Temporary segment not found"}, + { 612, "Segment in use"}, + { 613, "ISP port limit overrun"}, + { 614, "No modems available"}, + { 615, "Calling number unacceptable"}, + { 616, "Called number unacceptable"}, + { 900, "Service Restored"}, + { 901, "Cold Boot"}, + { 902, "Warm Boot"}, + { 903, "MGC Directed Change"}, + { 904, "Termination malfunctioning"}, + { 905, "Termination taken out of service"}, + { 906, "Loss of lower layer connectivity (e.g. downstream sync)"}, + { 907, "Transmission Failure"}, + { 908, "MG Impending Failure"}, + { 909, "MGC Impending Failure"}, + { 910, "Media Capability Failure"}, + { 911, "Modem Capability Failure"}, + { 912, "Mux Capability Failure"}, + { 913, "Signal Capability Failure"}, + { 914, "Event Capability Failure"}, + { 915, "State Loss"}, + { 916, "Packages Change"}, + { 917, "Capabilities Change"}, + { 918, "Cancel Graceful"}, + { 919, "Warm Failover"}, + { 920, "Cold Failover"}, + {0,NULL} +}; + +static const value_string request_types[] = { + { 0, "unknown" }, + { 1, "add" }, + { 2, "move" }, + { 3, "mod" }, + { 4, "subtract" }, + { 5, "auditCap" }, + { 6, "auditValue" }, + { 7, "notify" }, + { 8, "serviceChange" } +}; + static int dissect_h248_trx_id(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) { guint64 trx_id = 0; gint8 class; @@ -323,18 +495,18 @@ static int dissect_h248_trx_id(gboolean implicit_tag, packet_info *pinfo, proto_ offset++; } if (trx_id > 0xffffffff) { - proto_tree_add_uint64_format(tree, hf_h248_transactionId_64, tvb, offset-len, len, - trx_id,"transactionId %" PRIu64, trx_id); + proto_item* pi = proto_tree_add_text(tree, tvb, offset-len, len,"transactionId %" PRIu64, trx_id); + proto_item_set_expert_flags(pi, PI_MALFORMED, PI_WARN); + + transaction_id = 0; + } else { - proto_tree_add_uint(tree, hf_h248_transactionId, tvb, offset-len, len, (guint32)trx_id); + proto_tree_add_uint(tree, hf_h248_transactionId, tvb, offset-len, len, (guint32)trx_id); + transaction_id = (guint32)trx_id; } } - if (check_col(pinfo->cinfo, COL_INFO)) { - col_clear(pinfo->cinfo, COL_INFO); - col_add_fstr(pinfo->cinfo, COL_INFO, "Trx %" PRIu64 " { ", trx_id); - } - - return offset; + + return offset; } static int dissect_h248_ctx_id(gboolean implicit_tag, packet_info *pinfo, proto_tree *tree, tvbuff_t *tvb, int offset) { @@ -342,10 +514,8 @@ static int dissect_h248_ctx_id(gboolean implicit_tag, packet_info *pinfo, proto_ gboolean pc; gint32 tag; guint32 len; - guint64 context_id = 0; + guint64 ctx_id = 0; guint32 i; - static gchar context_string[64]; - static gchar context_string_long[64]; if(!implicit_tag){ offset=dissect_ber_identifier(pinfo, tree, tvb, offset, &class, &pc, &tag); @@ -359,38 +529,23 @@ static int dissect_h248_ctx_id(gboolean implicit_tag, packet_info *pinfo, proto_ THROW(BoundsError); } else { for(i=1;i<=len;i++){ - context_id=(context_id<<8)|tvb_get_guint8(tvb, offset); + ctx_id=(ctx_id<<8)|tvb_get_guint8(tvb, offset); offset++; } - - if (context_id == 0x0000000 ) { - strncpy(context_string,"Ctx 0",sizeof(context_string)); - strncpy(context_string_long,"0 (Null Context)",sizeof(context_string)); - } else if (context_id == 0xFFFFFFFF ) { - strncpy(context_string,"Ctx *",sizeof(context_string)); - strncpy(context_string_long,"* (All Contexts)",sizeof(context_string)); - } else if (context_id == 0xFFFFFFFE ) { - strncpy(context_string,"Ctx $",sizeof(context_string)); - strncpy(context_string_long,"$ (Choose One)",sizeof(context_string)); - } else { - g_snprintf(context_string,sizeof(context_string),"Ctx 0x%" PRIx64, context_id); - g_snprintf(context_string_long,sizeof(context_string),"0x%" PRIx64, context_id); - } - - if (context_id > 0xffffffff) { - proto_tree_add_uint64_format(tree, hf_h248_contextId_64, - tvb, offset-len, len, - context_id, "contextId: %s", context_string_long); + if (ctx_id > 0xffffffff) { + proto_item* pi = proto_tree_add_text(tree, tvb, offset-len, len, + "contextId: %" PRIu64, ctx_id); + proto_item_set_expert_flags(pi, PI_MALFORMED, PI_WARN); + + context_id = 0xfffffffd; + } else { - proto_tree_add_uint_format(tree, hf_h248_contextId, tvb, offset-len, len, - (guint32)context_id, "contextId: %s", context_string_long); + proto_tree_add_uint(tree, hf_h248_context_id, tvb, offset-len, len, (guint32)ctx_id); + + context_id = (guint32) ctx_id; } } - if (check_col(pinfo->cinfo, COL_INFO)) { - col_append_fstr(pinfo->cinfo, COL_INFO, "%s { ", context_string); - } - return offset; } @@ -705,50 +860,409 @@ dissect_h248_MtpAddress(gboolean implicit_tag, tvbuff_t *tvb, int offset, packet proto_tree_add_uint(mtp_tree, hf_h248_mtpaddress_ni, tvb, old_offset, offset-old_offset, val&0x03); proto_tree_add_uint(mtp_tree, hf_h248_mtpaddress_pc, tvb, old_offset, offset-old_offset, val>>2); } + + return offset; +} +static gchar* cmd_str(h248_cmdmsg_info_t* cmdmsg) { + static gchar* command_strings[][2] = { + { "unkReq", "unkReply" }, + { "addReq", "addReply" }, + { "moveReq", "moveReply" }, + { "modReq", "modReply" }, + { "subtractReq", "subtractReply" }, + { "auditCapRequest", "auditCapReply" }, + { "auditValueRequest", "auditValueReply" }, + { "notifyReq", "notifyReply" }, + { "serviceChangeReq", "serviceChangeReply" } + }; + + gchar* ctx_str; + gchar* cmd_str; + gchar* param_str; + + switch (cmdmsg->msg_type) { + case H248_TRX_REQUEST: + cmd_str = command_strings[cmdmsg->cmd_type][0]; + + if (cmdmsg->term_is_wildcard) { + param_str = "Term *"; + } else { + param_str = ep_strdup_printf("Term %s",cmdmsg->term_id); + } + + break; + case H248_TRX_REPLY: + cmd_str = command_strings[cmdmsg->cmd_type][1]; + + if ( cmdmsg->error_code ) { + param_str = ep_strdup_printf("Error %u",cmdmsg->error_code); + } else { + if (cmdmsg->term_is_wildcard) { + param_str = "Term *"; + } else { + param_str = ep_strdup_printf("Term %s",cmdmsg->term_id); + } + } + break; + case H248_TRX_PENDING: + return ep_strdup_printf("T %x { Pending }", cmdmsg->transaction_id); + case H248_TRX_ACK: + return ep_strdup_printf("T %x { Ack }", cmdmsg->transaction_id); + default: + return "[ Bad Command ]"; + }; + + switch (cmdmsg->context_id) { + case NULL_CONTEXT: ctx_str = "0"; break; + case CHOOSE_CONTEXT: ctx_str = "$"; break; + case ALL_CONTEXTS: ctx_str = "*"; break; + default: ctx_str = ep_strdup_printf("%u",cmdmsg->context_id); break; + } + + return ep_strdup_printf("T %x { C %s { %s { %s }}} ", + cmdmsg->transaction_id, ctx_str, cmd_str, param_str ); + +} - return offset; +static proto_tree* cmdmsg_tree(h248_cmdmsg_info_t* cmdmsg) { + proto_item* pi = proto_tree_add_text(h248_tree,NULL,0,0,"cmd msg"); + proto_tree* debug_tree = proto_item_add_subtree(pi,ett_debug); + + proto_tree_add_text(debug_tree,NULL,0,0,"transaction_id = %x",cmdmsg->transaction_id); + proto_tree_add_text(debug_tree,NULL,0,0,"context_id = %x",cmdmsg->context_id); + proto_tree_add_text(debug_tree,NULL,0,0,"cmd_type = %u",cmdmsg->cmd_type); + proto_tree_add_text(debug_tree,NULL,0,0,"msg_type = %u",cmdmsg->msg_type); + proto_tree_add_text(debug_tree,NULL,0,0,"error_code = %u",cmdmsg->error_code); + proto_tree_add_text(debug_tree,NULL,0,0,"term_is_wildcard = %x", cmdmsg->term_is_wildcard); + proto_tree_add_text(debug_tree,NULL,0,0,"term_id = %s", cmdmsg->term_id); + + return debug_tree; } -#include "packet-h248-fn.c" +static void analyze_h248_cmd(packet_info* pinfo, h248_cmdmsg_info_t* cmdmsg) { + h248_cmd_info_t* cmd_info; + static h248_cmd_info_t no_cmd_info = {NULL,0,H248_CMD_NONE,0,0,FALSE,0,NULL,NULL,NULL}; + gchar* low_addr; + gchar* high_addr; + guint framenum = pinfo->fd->num; + gchar* cmd_key; -static void -dissect_h248(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) -{ - proto_item *h248_item; - proto_tree *h248_tree = NULL; - - /* Check if it is actually a text based h248 encoding, which we call - megaco in ehtereal. - */ - if(tvb_length(tvb)>=6){ - if(!tvb_strneql(tvb, 0, "MEGACO", 6)){ - static dissector_handle_t megaco_handle=NULL; - if(!megaco_handle){ - megaco_handle = find_dissector("megaco"); - } - if(megaco_handle){ - call_dissector(megaco_handle, tvb, pinfo, tree); + cmd_info = g_hash_table_lookup(transactions_by_framenum,GUINT_TO_POINTER(framenum)); + + if (cmd_info == &no_cmd_info) { + cmdmsg->cmd_info = NULL; + return; + } else if ( cmd_info == NULL ) { + gboolean dup = FALSE; + + if (CMP_ADDRESS(&(pinfo->net_src), &(pinfo->net_dst)) < 0) { + low_addr = address_to_str(&(pinfo->net_src)); + high_addr = address_to_str(&(pinfo->net_dst)); + } else { + low_addr = address_to_str(&(pinfo->net_dst)); + high_addr = address_to_str(&(pinfo->net_src)); + } + + cmd_key = ep_strdup_printf("%s <-> %s : %x",low_addr,high_addr,cmdmsg->transaction_id); + + cmd_info = g_hash_table_lookup(transactions,cmd_key); + + if ( cmd_info ) { + switch (cmdmsg->msg_type) { + case H248_TRX_REQUEST: + dup = TRUE; + break; + case H248_TRX_REPLY: + if (cmd_info->response_frame) { + dup = TRUE; + } else { + cmd_info->response_frame = framenum; + cmd_info->error_code = cmdmsg->error_code; + } + break; + default: + break; + } + } else { + + switch (cmdmsg->msg_type) { + case H248_TRX_REQUEST: + cmd_info = se_alloc(sizeof(h248_cmd_info_t)); + cmd_info->key = se_strdup(cmd_key); + cmd_info->trx_id = cmdmsg->transaction_id; + cmd_info->type = cmdmsg->cmd_type; + cmd_info->request_frame = framenum; + cmd_info->response_frame = 0; + cmd_info->choose_ctx = (cmdmsg->context_id == CHOOSE_CONTEXT); + cmd_info->error_code = 0; + cmd_info->context = NULL; + cmd_info->next = NULL; + cmd_info->last = NULL; + + g_hash_table_insert(transactions,cmd_info->key,cmd_info); + break; + default: + cmd_info = &no_cmd_info; + break; + } + + } + + g_hash_table_insert(transactions_by_framenum,GUINT_TO_POINTER(framenum),cmd_info); + + cmdmsg->cmd_info = cmd_info; + + if ( cmd_info && (! cmd_info->context || cmd_info->context->ctx_id == 0 ) ) { + h248_context_info_t** ctx_ptr; + gchar* ctx_key; + + if (cmd_info->choose_ctx) { + /* the fisrt transaction of a new context */ + + ctx_key = ep_strdup_printf("%s-%s-%i",low_addr,high_addr,cmdmsg->transaction_id); + + switch (cmdmsg->msg_type) { + case H248_TRX_REQUEST: { + cmd_info->context = se_alloc(sizeof(h248_context_info_t)); + cmd_info->context->key = NULL; + cmd_info->context->ctx_id = 0; + cmd_info->context->creation_frame = framenum; + cmd_info->context->cmds = cmd_info; + cmd_info->context->prior = NULL; + + cmd_info->next = NULL; + cmd_info->last = cmd_info; + + /* + * XXX: leak: the "transaction key" of a context should be freed + * as we get the context_id one, there's no need for it afterwards. + * + * We're no using an ep_allocated one because g_hashtables do not + * behave propperly if the key changes. + * + * g_strdup/g_free should be used instead of se_strdup. + */ + + g_hash_table_insert(contexts_creating,se_strdup(ctx_key),cmd_info->context); + + } + break; + case H248_TRX_REPLY: { + + /* XXX: former leak: this one should be an extended lookup to g_free the key */ + if (( cmd_info->context = g_hash_table_lookup(contexts_creating,ctx_key) )) { + + ctx_key = ep_strdup_printf("%s<->%s : %.8x",low_addr,high_addr,cmdmsg->context_id); + + cmd_info->context->ctx_id = cmdmsg->context_id; + + if ((ctx_ptr = g_hash_table_lookup(contexts,ctx_key))) { + cmd_info->context->prior = *ctx_ptr; + cmd_info->context->key = cmd_info->context->prior->key; + *ctx_ptr = cmd_info->context; + } else { + ctx_ptr = se_alloc(sizeof(void*)); + *ctx_ptr = cmd_info->context; + cmd_info->context->key = se_strdup(ctx_key); + + g_hash_table_insert(contexts,cmd_info->context->key,ctx_ptr); + } + } + } + break; + default: + break; + } + } else { + ctx_key = ep_strdup_printf("%s<->%s : %.8x",low_addr,high_addr,cmdmsg->context_id); + + if (( ctx_ptr = g_hash_table_lookup(contexts,ctx_key) )) { + cmd_info->context = *ctx_ptr; + cmd_info->context->cmds->last->next = cmd_info; + cmd_info->context->cmds->last = cmd_info; + } + } + + if (cmd_info && cmd_info->context) { + cmd_info->context->last_frame = framenum; + } + } + } else { + cmdmsg->cmd_info = cmd_info; return; - } } - } - - /* Make entry in the Protocol column on summary display */ - if (check_col(pinfo->cinfo, COL_PROTOCOL)) - col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.248"); + +} - if (tree) { - h248_item = proto_tree_add_item(tree, proto_h248, tvb, 0, -1, FALSE); - h248_tree = proto_item_add_subtree(h248_item, ett_h248); - } +static void analysis_tree(packet_info* pinfo, tvbuff_t *tvb, proto_tree* tree, h248_cmdmsg_info_t* cmdmsg) { + h248_cmd_info_t* cmd_info = cmdmsg->cmd_info; + guint framenum = pinfo->fd->num; + + if (cmd_info) { + proto_item* pi = proto_tree_add_string(tree,hf_h248_cmd_trx,tvb,0,0,cmd_info->key); + proto_tree* cmd_tree = proto_item_add_subtree(pi, ett_cmd); + PROTO_ITEM_SET_GENERATED(pi); + + switch (cmdmsg->msg_type) { + case H248_TRX_REQUEST: + if (cmd_info->response_frame) { + pi = proto_tree_add_uint(cmd_tree,hf_h248_cmd_reply,tvb,0,0,cmd_info->response_frame); + } else { + pi = proto_tree_add_text(cmd_tree,tvb,0,0,"No response"); + proto_item_set_expert_flags(pi, PI_SEQUENCE, PI_NOTE); + } + PROTO_ITEM_SET_GENERATED(pi); + + if (cmd_info->request_frame != framenum) { + pi = proto_tree_add_uint(cmd_tree,hf_h248_cmd_dup_request,tvb,0,0,cmd_info->request_frame); + proto_item_set_expert_flags(pi, PI_SEQUENCE, PI_NOTE); + PROTO_ITEM_SET_GENERATED(pi); + } + break; + case H248_TRX_REPLY: + + if (cmd_info->request_frame) { + proto_tree_add_uint(cmd_tree,hf_h248_cmd_request,tvb,0,0,cmd_info->request_frame); + } else { + pi = proto_tree_add_text(cmd_tree,tvb,0,0,"No request"); + proto_item_set_expert_flags(pi, PI_SEQUENCE, PI_NOTE); + } + + if (cmd_info->response_frame != framenum) { + pi = proto_tree_add_uint(cmd_tree,hf_h248_cmd_dup_reply,tvb,0,0,cmd_info->response_frame); + proto_item_set_expert_flags(pi, PI_SEQUENCE, PI_NOTE); + } + break; + default: + /* + * XXX: TODO Pending and Ack + * We need a list of frames or at least a counter of Pendings; these can be many. + * Pendings are known to be synthoms of problems. + */ + return; + } + + if (cmd_info->choose_ctx) { + pi = proto_tree_add_boolean(cmd_tree,hf_h248_cmd_start,tvb,0,0,TRUE); + PROTO_ITEM_SET_GENERATED(pi); + proto_item_set_expert_flags(pi, PI_SEQUENCE, PI_NOTE); + } + + if (cmd_info->error_code) { + pi = proto_tree_add_uint(cmd_tree,hf_h248_cmd_error,tvb,0,0,cmd_info->error_code); + PROTO_ITEM_SET_GENERATED(pi); + expert_add_info_format(pinfo, pi, PI_RESPONSE_CODE, PI_WARN, "Errored Command"); + } + + + if (cmd_info->context) { + proto_tree* ctx_tree; + proto_tree* cmds_tree; + h248_cmd_info_t* cmd; + + if (cmd_info->context->key) { + pi = proto_tree_add_string(tree,hf_h248_cmd_ctx,tvb,0,0,cmd_info->context->key); + } else { + pi = proto_tree_add_text(tree,tvb,0,0,"Embryonic Context"); + } + ctx_tree = proto_item_add_subtree(pi, ett_ctx); + PROTO_ITEM_SET_GENERATED(pi); + + pi = proto_tree_add_uint(ctx_tree,hf_h248_ctx_start,tvb,0,0,cmd_info->context->creation_frame); + PROTO_ITEM_SET_GENERATED(pi); + + pi = proto_tree_add_uint(ctx_tree,hf_h248_ctx_last,tvb,0,0,cmd_info->context->last_frame); + PROTO_ITEM_SET_GENERATED(pi); + + pi = proto_tree_add_text(ctx_tree,tvb,0,0,"[ Commands ]"); + cmds_tree = proto_item_add_subtree(pi, ett_ctx_cmds); + + for(cmd = cmd_info->context->cmds; cmd; cmd = cmd->next) { + proto_tree* ctx_cmd_tree; + + pi = proto_tree_add_uint(cmds_tree,hf_h248_ctx_cmd_type,tvb,0,0,cmd->type); + PROTO_ITEM_SET_GENERATED(pi); + ctx_cmd_tree = proto_item_add_subtree(pi,ett_ctx_cmd); + + if (cmd == cmd_info ) { + pi = proto_tree_add_uint_format(ctx_cmd_tree,hf_h248_ctx_cmd,tvb,0,0,cmd->trx_id,"This Transaction: %u",cmd->trx_id); + } else { + pi = proto_tree_add_uint_format(ctx_cmd_tree,hf_h248_ctx_cmd,tvb,0,0,cmd->trx_id,"Transaction: %u",cmd->trx_id); + } + PROTO_ITEM_SET_GENERATED(pi); + + pi = proto_tree_add_uint(ctx_cmd_tree,hf_h248_ctx_cmd_request,tvb,0,0,cmd->request_frame); + PROTO_ITEM_SET_GENERATED(pi); + + pi = proto_tree_add_uint(ctx_cmd_tree,hf_h248_ctx_cmd_reply,tvb,0,0,cmd->response_frame); + PROTO_ITEM_SET_GENERATED(pi); + + if (cmd->error_code) { + pi = proto_tree_add_uint(ctx_cmd_tree,hf_h248_ctx_cmd_error,tvb,0,0,cmd->error_code); + PROTO_ITEM_SET_GENERATED(pi); + expert_add_info_format(pinfo, pi, PI_RESPONSE_CODE, PI_NOTE, "Errored Context"); + } + + } + + } + } +} - dissect_h248_MegacoMessage(FALSE, tvb, 0, pinfo, h248_tree, -1); +#include "packet-h248-fn.c" +static void +dissect_h248(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) +{ + proto_item *h248_item; + + h248_tree = NULL; + + /* Check if it is actually a text based h248 encoding, which we call + megaco in ehtereal. + */ + if(tvb_length(tvb)>=6){ + if(!tvb_strneql(tvb, 0, "MEGACO", 6)){ + static dissector_handle_t megaco_handle=NULL; + if(!megaco_handle){ + megaco_handle = find_dissector("megaco"); + } + if(megaco_handle){ + call_dissector(megaco_handle, tvb, pinfo, tree); + return; + } + } + } + + /* Make entry in the Protocol column on summary display */ + if (check_col(pinfo->cinfo, COL_PROTOCOL)) + col_set_str(pinfo->cinfo, COL_PROTOCOL, "H.248"); + + if (tree) { + h248_item = proto_tree_add_item(tree, proto_h248, tvb, 0, -1, FALSE); + h248_tree = proto_item_add_subtree(h248_item, ett_h248); + } + + dissect_h248_MegacoMessage(FALSE, tvb, 0, pinfo, h248_tree, -1); + } +static void h248_init(void) { + + if (transactions) g_hash_table_destroy(transactions); + if (transactions_by_framenum) g_hash_table_destroy(transactions_by_framenum); + if (contexts_creating) g_hash_table_destroy(contexts_creating); + if (contexts) g_hash_table_destroy(contexts); + + transactions = g_hash_table_new(g_str_hash,g_str_equal); + transactions_by_framenum = g_hash_table_new(g_direct_hash,g_direct_equal); + contexts_creating = g_hash_table_new(g_str_hash,g_str_equal); + contexts = g_hash_table_new(g_str_hash,g_str_equal); + +} /*--- proto_register_h248 ----------------------------------------------*/ void proto_register_h248(void) { @@ -761,19 +1275,13 @@ void proto_register_h248(void) { { &hf_h248_mtpaddress_pc, { "PC", "h248.mtpaddress.pc", FT_UINT32, BASE_DEC, NULL, 0, "PC", HFILL }}, - { &hf_h248_transactionId_64, { - "transactionId", "h248.transactionId", - FT_UINT64, BASE_HEX, NULL, 0,"", HFILL }}, - { &hf_h248_contextId_64, { - "contextId", "h248.contextId", - FT_UINT64, BASE_HEX, NULL, 0,"", HFILL }}, { &hf_h248_package_name, { "Package", "h248.package_name", FT_UINT16, BASE_HEX, VALS(package_name_vals), 0, "Package", HFILL }}, { &hf_h248_event_name, { "Package and Event name", "h248.event_name", FT_UINT32, BASE_HEX, VALS(event_name_vals), 0, "Package", HFILL }}, - { &hf_h248_signal_name, { + { &hf_h248_signal_name, { "Package and Signal name", "h248.signal_name", FT_UINT32, BASE_HEX, VALS(signal_name_vals), 0, "Package", HFILL }}, { &hf_h248_package_bcp_BNCChar_PDU, @@ -832,6 +1340,30 @@ void proto_register_h248(void) { { "Initialisation Direction", "h248.package_3GUP.initdir", FT_UINT32, BASE_DEC, VALS(h248_3GUP_initdir_vals), 0, "Initialisation Direction", HFILL }}, + { &hf_h248_error_code, + { "errorCode", "h248.errorCode", + FT_UINT32, BASE_DEC, VALS(h248_reasons), 0, + "ErrorDescriptor/errorCode", HFILL }}, + { &hf_h248_context_id, + { "contextId", "h248.contextId", + FT_UINT32, BASE_DEC, VALS(h248_reasons), 0, + "Context ID", HFILL }}, + + { &hf_h248_cmd_trx, { "Transaction", "h248.trx", FT_STRING, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_h248_cmd_request, { "Request for this Reply", "h248.cmd.request", FT_FRAMENUM, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_h248_cmd_reply, { "Reply to this Request", "h248.cmd.reply", FT_FRAMENUM, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_h248_cmd_dup_request, { "This Request is a Duplicate of", "h248.cmd.dup_request", FT_FRAMENUM, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_h248_cmd_dup_reply, { "This Reply is a Duplicate of", "h248.cmd.dup_reply", FT_FRAMENUM, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_h248_cmd_start, { "This Transaction Starts a New Context", "h248.cmd.start", FT_BOOLEAN, BASE_NONE, NULL, 0, "", HFILL }}, + { &hf_h248_cmd_error, { "Error", "h248.cmd.error", FT_UINT32, BASE_DEC, VALS(h248_reasons), 0, "", HFILL }}, + { &hf_h248_cmd_ctx, { "Context", "h248.ctx", FT_STRING, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_h248_ctx_start, { "Start", "h248.ctx.start", FT_FRAMENUM, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_h248_ctx_last, { "Last", "h248.ctx.last", FT_FRAMENUM, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_h248_ctx_cmd, { "Command", "h248.ctx.cmd", FT_UINT32, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_h248_ctx_cmd_type, { "Command Type", "h248.ctx.cmd.type", FT_UINT32, BASE_DEC, VALS(request_types), 0, "", HFILL }}, + { &hf_h248_ctx_cmd_request, { "Request", "h248.ctx.cmd.request", FT_FRAMENUM, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_h248_ctx_cmd_reply, { "Reply", "h248.ctx.cmd.reply", FT_FRAMENUM, BASE_DEC, NULL, 0, "", HFILL }}, + { &hf_h248_ctx_cmd_error, { "Error", "h248.ctx.cmd.error", FT_UINT32, BASE_DEC, VALS(h248_reasons), 0, "", HFILL }}, #include "packet-h248-hfarr.c" }; @@ -841,9 +1373,18 @@ void proto_register_h248(void) { &ett_h248, &ett_mtpaddress, &ett_packagename, - &ett_codec, + &ett_codec, + &ett_cmd, + &ett_ctx, + &ett_ctx_cmd, + &ett_ctx_cmds, + &ett_debug, + #include "packet-h248-ettarr.c" }; + + module_t *h248_module; + /* Register protocol */ proto_h248 = proto_register_protocol(PNAME, PSNAME, PFNAME); @@ -853,11 +1394,23 @@ void proto_register_h248(void) { proto_register_field_array(proto_h248, hf, array_length(hf)); proto_register_subtree_array(ett, array_length(ett)); +#if 0 /* register a dissector table packages can attach to */ - h248_package_bin_dissector_table = register_dissector_table("h248.package.bin", "Binary H.248 Package Dissectors", FT_UINT16,BASE_HEX); + h248_package_signals = g_hash_table_new(g_hash_direct,g_direct_equal); + h248_package_events = g_hash_table_new(g_hash_direct,g_direct_equal); + h248_package_properties = g_hash_table_new(g_hash_direct,g_direct_equal); +#endif -} + h248_module = prefs_register_protocol(proto_h248, h248_init); + + prefs_register_bool_preference(h248_module, "ctx_info", + "Keep Context Information", + "Whether persistent context information is to be kept", + &keep_persistent_data); + + register_init_routine( &h248_init ); +} /*--- proto_reg_handoff_h248 -------------------------------------------*/ void proto_reg_handoff_h248(void) { @@ -871,3 +1424,25 @@ void proto_reg_handoff_h248(void) { dissector_add("sctp.ppi", H248_PAYLOAD_PROTOCOL_ID, h248_handle); } +#ifndef ENABLE_STATIC + +#include <gmodule.h> + +G_MODULE_EXPORT const gchar version[] = "0.0.0"; + +G_MODULE_EXPORT void +plugin_register(void) +{ + /* register the new protocol, protocol fields, and subtrees */ + if (proto_h248 == -1) { /* execute protocol initialization only once */ + proto_register_h248(); + } +} + +G_MODULE_EXPORT void +plugin_reg_handoff(void){ + proto_reg_handoff_h248(); +} + +#endif + diff --git a/asn1/h248/packet-h248-template.h b/asn1/h248/packet-h248-template.h index a70b7fa14a..ae3d790275 100644 --- a/asn1/h248/packet-h248-template.h +++ b/asn1/h248/packet-h248-template.h @@ -28,5 +28,80 @@ /*#include "packet-h248-exp.h"*/ -#endif /* PACKET_H248_H */ +typedef enum { + H248_CMD_NONE, + H248_CMD_ADD, + H248_CMD_MOVE, + H248_CMD_MOD, + H248_CMD_SUB, + H248_CMD_AUDITCAP, + H248_CMD_AUDITVAL, + H248_CMD_NOTIFY, + H248_CMD_SVCCHG, +} h248_cmd_type_t; + +typedef enum { + H248_TRX_NONE, + H248_TRX_REQUEST, + H248_TRX_PENDING, + H248_TRX_REPLY, + H248_TRX_ACK, +} h248_msg_type_t; + +/* per command info */ +typedef struct _h248_cmd_info_t h248_cmd_info_t; + +/* per context info */ +typedef struct _h248_context_info_t h248_context_info_t; + +/* per command message info */ +typedef struct _h248_cmdmsg_info_t { + guint32 transaction_id; + guint32 context_id; + guint offset; + h248_cmd_type_t cmd_type; + h248_msg_type_t msg_type; + guint error_code; + gboolean term_is_wildcard; + gchar* term_id; + h248_cmd_info_t* cmd_info; +} h248_cmdmsg_info_t; + + +struct _h248_cmd_info_t { + gchar* key; + + guint32 trx_id; + h248_cmd_type_t type; + + guint request_frame; + guint response_frame; + + gboolean choose_ctx; + guint error_code; + + h248_context_info_t* context; + + h248_cmd_info_t* next; + h248_cmd_info_t* last; +}; +struct _h248_context_info_t { + gchar* key; + + guint32 ctx_id; + + guint creation_frame; + guint last_frame; + + h248_cmd_info_t* cmds; + h248_context_info_t* prior; +}; + +typedef void (*h248_dissect_pkg_item_t)(gboolean implicit_tag, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree); + +extern void h248_add_package_property(guint package, guint property, h248_dissect_pkg_item_t); +extern void h248_add_package_event(guint package, guint property, h248_dissect_pkg_item_t); +extern void h248_add_package_signal(guint package, guint property, h248_dissect_pkg_item_t); + +#endif /* PACKET_H248_H */ |