Move Gateway Control Protocol (Context Tracking) into packet-h248.h

The Gateway Control Protocol (Context Tracking) is used by both H248
and MEGACO, so the functionality was refactored to epan, but should
really be kept in the dissector directory to minimize (and eventually
completely remove) the epan directory's dependence on it.

Change-Id: I387b46aecde97234086bfdb7d8c546854fa301cd
Reviewed-on: https://code.wireshark.org/review/15798
Petri-Dish: Michael Mann <mmann78@netscape.net>
Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org>
Reviewed-by: Michael Mann <mmann78@netscape.net>
This commit is contained in:
Michael Mann 2016-06-10 00:00:39 -04:00
parent 68ef5dbf2f
commit 2d095de053
14 changed files with 1849 additions and 1041 deletions

View File

@ -121,7 +121,6 @@ set(LIBWIRESHARK_FILES
frame_data_sequence.c
funnel.c
g_int64_hash_routines.c
gcp.c
geoip_db.c
golay.c
guid-utils.c

View File

@ -59,7 +59,6 @@ LIBWIRESHARK_SRC = \
frame_data_sequence.c \
funnel.c \
g_int64_hash_routines.c \
gcp.c \
geoip_db.c \
golay.c \
guid-utils.c \
@ -204,7 +203,6 @@ LIBWIRESHARK_INCLUDES = \
funnel.h \
g_int64_hash_routines.h \
garrayfix.h \
gcp.h \
geoip_db.h \
golay.h \
guid-utils.h \

View File

@ -25,10 +25,14 @@
#include "config.h"
#include <packet.h>
#include <epan/packet.h>
#include <epan/exceptions.h>
#include <epan/tap.h>
#include <epan/asn1.h>
#include <epan/prefs.h>
#include <epan/exported_pdu.h>
#include "packet-alcap.h"
#include "packet-ber.h"
#include "packet-tpkt.h"
#include "packet-mtp3.h"
#include "packet-h248.h"
@ -100,10 +104,731 @@ static expert_field ei_h248_octet_string_expected = EI_INIT;
static dissector_table_t subdissector_table;
static wmem_tree_t* msgs = NULL;
static wmem_tree_t* trxs = NULL;
static wmem_tree_t* ctxs_by_trx = NULL;
static wmem_tree_t* ctxs = NULL;
/* Gateway Control Protocol -- Context Tracking */
const value_string gcp_cmd_type[] = {
{ GCP_CMD_NONE, "NoCommand"},
{ GCP_CMD_ADD_REQ, "addReq"},
{ GCP_CMD_MOVE_REQ, "moveReq"},
{ GCP_CMD_MOD_REQ, "modReq"},
{ GCP_CMD_SUB_REQ, "subtractReq"},
{ GCP_CMD_AUDITCAP_REQ, "auditCapRequest"},
{ GCP_CMD_AUDITVAL_REQ, "auditValueRequest"},
{ GCP_CMD_NOTIFY_REQ, "notifyReq"},
{ GCP_CMD_SVCCHG_REQ, "serviceChangeReq"},
{ GCP_CMD_TOPOLOGY_REQ, "topologyReq"},
{ GCP_CMD_CTX_ATTR_AUDIT_REQ, "ctxAttrAuditReq"},
{ GCP_CMD_ADD_REPLY, "addReply"},
{ GCP_CMD_MOVE_REPLY, "moveReply"},
{ GCP_CMD_MOD_REPLY, "modReply"},
{ GCP_CMD_SUB_REPLY, "subtractReply"},
{ GCP_CMD_AUDITCAP_REPLY, "auditCapReply"},
{ GCP_CMD_AUDITVAL_REPLY, "auditValReply"},
{ GCP_CMD_NOTIFY_REPLY, "notifyReply"},
{ GCP_CMD_SVCCHG_REPLY, "serviceChangeReply"},
{ GCP_CMD_TOPOLOGY_REPLY, "topologyReply"},
{ 0, NULL }
};
const value_string gcp_term_types[] = {
{ GCP_TERM_TYPE_AAL1, "aal1" },
{ GCP_TERM_TYPE_AAL2, "aal2" },
{ GCP_TERM_TYPE_AAL1_STRUCT, "aal1struct" },
{ GCP_TERM_TYPE_IP_RTP, "ipRtp" },
{ GCP_TERM_TYPE_TDM, "tdm" },
{ 0, NULL }
};
static wmem_tree_t* gcp_msgs = NULL;
static wmem_tree_t* gcp_trxs = NULL;
static wmem_tree_t* gcp_ctxs_by_trx = NULL;
static wmem_tree_t* gcp_ctxs = NULL;
gcp_msg_t* gcp_msg(packet_info* pinfo, int o, gboolean keep_persistent_data) {
gcp_msg_t* m;
guint32 framenum = (guint32)pinfo->num;
guint32 offset = (guint32)o;
address* src = &(pinfo->src);
address* dst = &(pinfo->dst);
address* lo_addr;
address* hi_addr;
if (keep_persistent_data) {
wmem_tree_key_t key[3];
key[0].length = 1;
key[0].key = &(framenum);
key[1].length = 1;
key[1].key = &offset;
key[2].length = 0;
key[2].key =NULL;
if (( m = (gcp_msg_t *)wmem_tree_lookup32_array(gcp_msgs,key) )) {
m->committed = TRUE;
return m;
} else {
m = wmem_new(wmem_file_scope(), gcp_msg_t);
m->framenum = framenum;
m->time = pinfo->abs_ts;
m->trxs = NULL;
m->committed = FALSE;
wmem_tree_insert32_array(gcp_msgs,key,m);
}
} else {
m = wmem_new0(wmem_packet_scope(), gcp_msg_t);
m->framenum = framenum;
m->trxs = NULL;
m->committed = FALSE;
}
if (cmp_address(src, dst) < 0) {
lo_addr = src;
hi_addr = dst;
} else {
lo_addr = dst;
hi_addr = src;
}
switch(lo_addr->type) {
case AT_NONE:
m->lo_addr = 0;
m->hi_addr = 0;
break;
case AT_IPv4:
memcpy((guint8*)&(m->hi_addr),hi_addr->data,4);
memcpy((guint8*)&(m->lo_addr),lo_addr->data,4);
break;
case AT_SS7PC:
m->hi_addr = mtp3_pc_hash((const mtp3_addr_pc_t *)hi_addr->data);
m->lo_addr = mtp3_pc_hash((const mtp3_addr_pc_t *)lo_addr->data);
break;
default:
/* XXX: heuristic and error prone */
m->hi_addr = g_str_hash(address_to_str(wmem_packet_scope(), hi_addr));
m->lo_addr = g_str_hash(address_to_str(wmem_packet_scope(), lo_addr));
break;
}
return m;
}
gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean keep_persistent_data) {
gcp_trx_t* t = NULL;
gcp_trx_msg_t* trxmsg;
if ( !m ) return NULL;
if (keep_persistent_data) {
if (m->committed) {
for ( trxmsg = m->trxs; trxmsg; trxmsg = trxmsg->next) {
if (trxmsg->trx && trxmsg->trx->id == t_id) {
return trxmsg->trx;
}
}
DISSECTOR_ASSERT_NOT_REACHED();
} else {
wmem_tree_key_t key[4];
key[0].length = 1;
key[0].key = &(m->hi_addr);
key[1].length = 1;
key[1].key = &(m->lo_addr);
key[2].length = 1;
key[2].key = &(t_id);
key[3].length = 0;
key[3].key = NULL;
trxmsg = wmem_new(wmem_file_scope(), gcp_trx_msg_t);
t = (gcp_trx_t *)wmem_tree_lookup32_array(gcp_trxs,key);
if (!t) {
t = wmem_new(wmem_file_scope(), gcp_trx_t);
t->initial = m;
t->id = t_id;
t->type = type;
t->pendings = 0;
t->error = 0;
t->cmds = NULL;
wmem_tree_insert32_array(gcp_trxs,key,t);
}
/* XXX: request, reply and ack + point to frames where they are */
switch ( type ) {
case GCP_TRX_PENDING:
t->pendings++;
break;
default:
break;
}
}
} else {
t = wmem_new(wmem_packet_scope(), gcp_trx_t);
trxmsg = wmem_new(wmem_packet_scope(), gcp_trx_msg_t);
t->initial = NULL;
t->id = t_id;
t->type = type;
t->pendings = 0;
t->error = 0;
t->cmds = NULL;
}
DISSECTOR_ASSERT(trxmsg);
trxmsg->trx = t;
trxmsg->next = NULL;
trxmsg->last = trxmsg;
if (m->trxs) {
m->trxs->last = m->trxs->last->next = trxmsg;
} else {
m->trxs = trxmsg;
}
return t;
}
gcp_ctx_t* gcp_ctx(gcp_msg_t* m, gcp_trx_t* t, guint32 c_id, gboolean persistent) {
gcp_ctx_t* context = NULL;
gcp_ctx_t** context_p = NULL;
if ( !m || !t ) return NULL;
if (persistent) {
wmem_tree_key_t ctx_key[4];
wmem_tree_key_t trx_key[4];
ctx_key[0].length = 1;
ctx_key[0].key = &(m->hi_addr);
ctx_key[1].length = 1;
ctx_key[1].key = &(m->lo_addr);
ctx_key[2].length = 1;
ctx_key[2].key = &(c_id);
ctx_key[3].length = 0;
ctx_key[3].key = NULL;
trx_key[0].length = 1;
trx_key[0].key = &(m->hi_addr);
trx_key[1].length = 1;
trx_key[1].key = &(m->lo_addr);
trx_key[2].length = 1;
trx_key[2].key = &(t->id);
trx_key[3].length = 0;
trx_key[3].key = NULL;
if (m->committed) {
if (( context = (gcp_ctx_t *)wmem_tree_lookup32_array(gcp_ctxs_by_trx,trx_key) )) {
return context;
} if ((context_p = (gcp_ctx_t **)wmem_tree_lookup32_array(gcp_ctxs,ctx_key))) {
context = *context_p;
do {
if (context->initial->framenum <= m->framenum) {
return context;
}
} while(( context = context->prev ));
DISSECTOR_ASSERT(! "a context should exist");
}
} else {
if (c_id == CHOOSE_CONTEXT) {
if (! ( context = (gcp_ctx_t *)wmem_tree_lookup32_array(gcp_ctxs_by_trx,trx_key))) {
context = wmem_new(wmem_file_scope(), gcp_ctx_t);
context->initial = m;
context->cmds = NULL;
context->id = c_id;
context->terms.last = &(context->terms);
context->terms.next = NULL;
context->terms.term = NULL;
wmem_tree_insert32_array(gcp_ctxs_by_trx,trx_key,context);
}
} else {
if (( context = (gcp_ctx_t *)wmem_tree_lookup32_array(gcp_ctxs_by_trx,trx_key) )) {
if (( context_p = (gcp_ctx_t **)wmem_tree_lookup32_array(gcp_ctxs,ctx_key) )) {
if (context != *context_p) {
if(context->id != CHOOSE_CONTEXT) {
context = wmem_new(wmem_file_scope(), gcp_ctx_t);
}
context->initial = m;
context->id = c_id;
context->cmds = NULL;
context->terms.last = &(context->terms);
context->terms.next = NULL;
context->terms.term = NULL;
context->prev = *context_p;
*context_p = context;
}
} else {
context_p = wmem_new(wmem_file_scope(), gcp_ctx_t*);
*context_p = context;
context->initial = m;
context->id = c_id;
wmem_tree_insert32_array(gcp_ctxs,ctx_key,context_p);
}
} else if (! ( context_p = (gcp_ctx_t**)wmem_tree_lookup32_array(gcp_ctxs,ctx_key) )) {
context = wmem_new(wmem_file_scope(), gcp_ctx_t);
context->initial = m;
context->id = c_id;
context->cmds = NULL;
context->terms.last = &(context->terms);
context->terms.next = NULL;
context->terms.term = NULL;
context_p = wmem_new(wmem_file_scope(), gcp_ctx_t*);
*context_p = context;
wmem_tree_insert32_array(gcp_ctxs,ctx_key,context_p);
} else {
context = *context_p;
}
}
}
} else {
context = wmem_new(wmem_packet_scope(), gcp_ctx_t);
context->initial = m;
context->cmds = NULL;
context->id = c_id;
context->terms.last = &(context->terms);
context->terms.next = NULL;
context->terms.term = NULL;
}
return context;
}
gcp_cmd_t* gcp_cmd(gcp_msg_t* m, gcp_trx_t* t, gcp_ctx_t* c, gcp_cmd_type_t type, guint offset, gboolean persistent) {
gcp_cmd_t* cmd;
gcp_cmd_msg_t* cmdtrx;
gcp_cmd_msg_t* cmdctx;
if ( !m || !t || !c ) return NULL;
if (persistent) {
if (m->committed) {
DISSECTOR_ASSERT(t->cmds != NULL);
for (cmdctx = t->cmds; cmdctx; cmdctx = cmdctx->next) {
cmd = cmdctx->cmd;
if (cmd->msg == m && cmd->offset == offset) {
return cmd;
}
}
DISSECTOR_ASSERT(!"called for a command that does not exist!");
return NULL;
} else {
cmd = wmem_new(wmem_file_scope(), gcp_cmd_t);
cmdtrx = wmem_new(wmem_file_scope(), gcp_cmd_msg_t);
cmdctx = wmem_new(wmem_file_scope(), gcp_cmd_msg_t);
}
} else {
cmd = wmem_new(wmem_packet_scope(), gcp_cmd_t);
cmdtrx = wmem_new(wmem_packet_scope(), gcp_cmd_msg_t);
cmdctx = wmem_new(wmem_packet_scope(), gcp_cmd_msg_t);
}
cmd->type = type;
cmd->offset = offset;
cmd->terms.term = NULL;
cmd->terms.next = NULL;
cmd->terms.last = &(cmd->terms);
cmd->str = NULL;
cmd->msg = m;
if ((type != GCP_CMD_NONE) && (!persistent)){
cmd->str = val_to_str_const(type, gcp_cmd_type, "Unknown");
}
cmd->trx = t;
cmd->ctx = c;
cmd->error = 0;
cmdctx->cmd = cmdtrx->cmd = cmd;
cmdctx->next = cmdtrx->next = NULL;
cmdctx->last = cmdtrx->last = NULL;
if (t->cmds) {
t->cmds->last->next = cmdtrx;
t->cmds->last = cmdtrx;
} else {
t->cmds = cmdtrx;
t->cmds->last = cmdtrx;
}
if (c->cmds) {
c->cmds->last->next = cmdctx;
c->cmds->last = cmdctx;
} else {
c->cmds = cmdctx;
c->cmds->last = cmdctx;
}
return cmd;
}
gcp_term_t* gcp_cmd_add_term(gcp_msg_t* m, gcp_trx_t* tr, gcp_cmd_t* c, gcp_term_t* t, gcp_wildcard_t wildcard, gboolean persistent) {
gcp_terms_t* ct;
gcp_terms_t* ct2;
static gcp_term_t all_terms = {"$",(const guint8*)"",1,GCP_TERM_TYPE_UNKNOWN,NULL,NULL,NULL};
if ( !c ) return NULL;
if ( wildcard == GCP_WILDCARD_CHOOSE) {
return &all_terms;
}
if (persistent) {
if ( c->msg->committed ) {
if (wildcard == GCP_WILDCARD_ALL) {
for (ct = c->ctx->terms.next; ct; ct = ct->next) {
/* XXX not handling more wilcards in one msg */
if ( ct->term->start == m ) {
return ct->term;
}
}
return NULL;
} else {
for (ct = c->ctx->terms.next; ct; ct = ct->next) {
if ( g_str_equal(ct->term->str,t->str) ) {
return ct->term;
}
}
return NULL;
}
} else {
for (ct = c->ctx->terms.next; ct; ct = ct->next) {
if ( g_str_equal(ct->term->str,t->str) || ct->term->start == m) {
break;
}
}
if ( ! ct ) {
if (wildcard == GCP_WILDCARD_ALL) {
ct = wmem_new(wmem_file_scope(), gcp_terms_t);
ct->next = NULL;
ct->term = wmem_new0(wmem_file_scope(), gcp_term_t);
ct->term->start = m;
ct->term->str = "*";
ct->term->buffer = NULL;
ct->term->len = 0;
c->terms.last = c->terms.last->next = ct;
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->ctx->terms.last->next = ct2;
c->ctx->terms.last = ct2;
return ct->term;
} else {
for (ct = c->ctx->terms.next; ct; ct = ct->next) {
/* XXX not handling more wilcards in one msg */
if ( ct->term->buffer == NULL && tr->cmds->cmd->msg == ct->term->start ) {
ct->term->str = wmem_strdup(wmem_file_scope(), t->str);
ct->term->buffer = (const guint8 *)wmem_memdup(wmem_file_scope(), t->buffer,t->len);
ct->term->len = t->len;
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->terms.last = c->terms.last->next = ct2;
return ct->term;
}
if ( g_str_equal(ct->term->str,t->str) ) {
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->terms.last = c->terms.last->next = ct2;
return ct->term;
}
}
ct = wmem_new(wmem_file_scope(), gcp_terms_t);
ct->next = NULL;
ct->term = wmem_new0(wmem_file_scope(), gcp_term_t);
ct->term->start = m;
ct->term->str = wmem_strdup(wmem_file_scope(), t->str);
ct->term->buffer = (const guint8 *)wmem_memdup(wmem_file_scope(), t->buffer,t->len);
ct->term->len = t->len;
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->terms.last = c->terms.last->next = ct2;
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->ctx->terms.last = c->ctx->terms.last->next = ct2;
return ct->term;
}
} else {
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->terms.last = c->terms.last->next = ct2;
return ct->term;
}
DISSECTOR_ASSERT_NOT_REACHED();
}
} else {
ct = wmem_new(wmem_packet_scope(), gcp_terms_t);
ct->term = t;
ct->next = NULL;
c->terms.last = c->terms.last->next = ct;
return t;
}
}
static const gchar* gcp_cmd_to_str(gcp_cmd_t* c, gboolean persistent) {
const gchar* s;
gcp_terms_t* term;
if ( !c ) return "-";
switch (c->type) {
case GCP_CMD_NONE:
return "-";
break;
case GCP_CMD_ADD_REQ:
s = "AddReq {";
break;
case GCP_CMD_MOVE_REQ:
s = "MoveReq {";
break;
case GCP_CMD_MOD_REQ:
s = "ModReq {";
break;
case GCP_CMD_SUB_REQ:
s = "SubReq {";
break;
case GCP_CMD_AUDITCAP_REQ:
s = "AuditCapReq {";
break;
case GCP_CMD_AUDITVAL_REQ:
s = "AuditValReq {";
break;
case GCP_CMD_NOTIFY_REQ:
s = "NotifyReq {";
break;
case GCP_CMD_SVCCHG_REQ:
s = "SvcChgReq {";
break;
case GCP_CMD_TOPOLOGY_REQ:
s = "TopologyReq {";
break;
case GCP_CMD_CTX_ATTR_AUDIT_REQ:
s = "CtxAttribAuditReq {";
break;
case GCP_CMD_ADD_REPLY:
s = "AddReply {";
break;
case GCP_CMD_MOVE_REPLY:
s = "MoveReply {";
break;
case GCP_CMD_MOD_REPLY:
s = "ModReply {";
break;
case GCP_CMD_SUB_REPLY:
s = "SubReply {";
break;
case GCP_CMD_AUDITCAP_REPLY:
s = "AuditCapReply {";
break;
case GCP_CMD_AUDITVAL_REPLY:
s = "AuditValReply {";
break;
case GCP_CMD_NOTIFY_REPLY:
s = "NotifyReply {";
break;
case GCP_CMD_SVCCHG_REPLY:
s = "SvcChgReply {";
break;
case GCP_CMD_TOPOLOGY_REPLY:
s = "TopologyReply {";
break;
case GCP_CMD_REPLY:
s = "ActionReply {";
break;
case GCP_CMD_OTHER_REQ:
s = "Request {";
break;
default:
s = "-";
break;
}
for (term = c->terms.next; term; term = term->next) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,term->term->str);
}
if (c->error) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s Error=%i",s,c->error);
}
s = wmem_strdup_printf(wmem_packet_scope(), "%s }", s);
if (persistent) {
if (! c->str) c->str = wmem_strdup(wmem_file_scope(), s);
} else {
c->str = s;
}
return s;
}
static const gchar* gcp_trx_to_str(gcp_msg_t* m, gcp_trx_t* t, gboolean persistent) {
gchar* s;
gcp_cmd_msg_t* c;
if ( !m || !t ) return "-";
s = wmem_strdup_printf(wmem_packet_scope(), "T %x { ",t->id);
if (t->cmds) {
if (t->cmds->cmd->ctx) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s C %x {",s,t->cmds->cmd->ctx->id);
for (c = t->cmds; c; c = c->next) {
if (c->cmd->msg == m) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,gcp_cmd_to_str(c->cmd,persistent));
}
}
s = wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,"}");
}
}
if (t->error) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s Error=%i",s,t->error);
}
return wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,"}");
}
const gchar* gcp_msg_to_str(gcp_msg_t* m, gboolean persistent) {
gcp_trx_msg_t* t;
const gchar* s = "";
if ( !m ) return "-";
for (t = m->trxs; t; t = t->next) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,gcp_trx_to_str(m,t->trx, persistent));
}
return s;
}
typedef struct _gcp_ctxs_t {
struct _gcp_ctx_t* ctx;
struct _gcp_ctxs_t* next;
} gcp_ctxs_t;
/*static const gchar* trx_types[] = {"None","Req","Reply","Pending","Ack"};*/
void gcp_analyze_msg(proto_tree* gcp_tree, packet_info* pinfo, tvbuff_t* gcp_tvb, gcp_msg_t* m, gcp_hf_ett_t* ids, expert_field* command_err) {
gcp_trx_msg_t* t;
gcp_ctxs_t contexts = {NULL,NULL};
gcp_ctxs_t* ctx_node;
gcp_cmd_msg_t* c;
for (t = m->trxs; t; t = t->next) {
for (c = t->trx->cmds; c; c = c->next) {
gcp_ctx_t* ctx = c->cmd->ctx;
for (ctx_node = contexts.next; ctx_node; ctx_node = ctx_node->next) {
if (ctx_node->ctx->id == ctx->id) {
break;
}
}
if (! ctx_node) {
ctx_node = wmem_new(wmem_packet_scope(), gcp_ctxs_t);
ctx_node->ctx = ctx;
ctx_node->next = contexts.next;
contexts.next = ctx_node;
}
}
}
for (ctx_node = contexts.next; ctx_node; ctx_node = ctx_node->next) {
gcp_ctx_t* ctx = ctx_node->ctx;
proto_item* ctx_item = proto_tree_add_uint(gcp_tree,ids->hf.ctx,gcp_tvb,0,0,ctx->id);
proto_tree* ctx_tree = proto_item_add_subtree(ctx_item,ids->ett.ctx);
gcp_terms_t *ctx_term;
PROTO_ITEM_SET_GENERATED(ctx_item);
if (ctx->cmds) {
proto_tree* history_tree = proto_tree_add_subtree(ctx_tree,gcp_tvb,0,0,ids->ett.ctx_cmds,NULL,"[ Command History ]");
for (c = ctx->cmds; c; c = c->next) {
proto_item* cmd_item = proto_tree_add_uint(history_tree,ids->hf.ctx_cmd,gcp_tvb,0,0,c->cmd->msg->framenum);
if (c->cmd->str) proto_item_append_text(cmd_item," %s ",c->cmd->str);
PROTO_ITEM_SET_GENERATED(cmd_item);
if (c->cmd->error) {
expert_add_info(pinfo, cmd_item, command_err);
}
}
}
if (( ctx_term = ctx->terms.next )) {
proto_tree* terms_tree = proto_tree_add_subtree(ctx_tree,gcp_tvb,0,0,ids->ett.ctx_terms,NULL,"[ Terminations Used ]");
for (; ctx_term; ctx_term = ctx_term->next ) {
if ( ctx_term->term && ctx_term->term->str) {
proto_item* pi = proto_tree_add_string(terms_tree,ids->hf.ctx_term,gcp_tvb,0,0,ctx_term->term->str);
proto_tree* term_tree = proto_item_add_subtree(pi,ids->ett.ctx_term);
PROTO_ITEM_SET_GENERATED(pi);
if (ctx_term->term->type) {
pi = proto_tree_add_uint(term_tree,ids->hf.ctx_term_type,gcp_tvb,0,0,ctx_term->term->type);
PROTO_ITEM_SET_GENERATED(pi);
}
if (ctx_term->term->bir) {
pi = proto_tree_add_string(term_tree,ids->hf.ctx_term_bir,gcp_tvb,0,0,ctx_term->term->bir);
PROTO_ITEM_SET_GENERATED(pi);
}
if (ctx_term->term->nsap) {
pi = proto_tree_add_string(term_tree,ids->hf.ctx_term_nsap,gcp_tvb,0,0,ctx_term->term->nsap);
PROTO_ITEM_SET_GENERATED(pi);
}
if (ctx_term->term->bir && ctx_term->term->nsap) {
gchar* tmp_key = wmem_strdup_printf(wmem_packet_scope(), "%s:%s",ctx_term->term->nsap,ctx_term->term->bir);
gchar* key = g_ascii_strdown(tmp_key, -1);
alcap_tree_from_bearer_key(term_tree, gcp_tvb, pinfo, key);
g_free(key);
}
}
}
}
}
}
/* END Gateway Control Protocol -- Context Tracking */
static gboolean keep_persistent_data = FALSE;
static guint global_udp_port = 2945;
@ -1672,14 +2397,12 @@ void proto_register_h248(void) {
"Desegment H.248 messages that span more TCP segments",
&h248_desegment);
msgs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
trxs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
ctxs_by_trx = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
ctxs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
gcp_msgs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
gcp_trxs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
gcp_ctxs_by_trx = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
gcp_ctxs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
h248_tap = register_tap("h248");
gcp_init();
}
/*--- proto_reg_handoff_h248 -------------------------------------------*/

View File

@ -24,10 +24,183 @@
*/
#ifndef PACKET_H248_H
#define PACKET_H248_H
#include <epan/gcp.h>
#include "ws_symbol_export.h"
/*#include "packet-h248-exp.h"*/
#include <epan/packet.h>
#include <epan/expert.h>
#include <wsutil/nstime.h>
/* Gateway Control Protocol -- Context Tracking */
typedef struct _gcp_hf_ett_t {
struct {
int ctx;
int ctx_cmd;
int ctx_term;
int ctx_term_type;
int ctx_term_bir;
int ctx_term_nsap;
} hf;
struct {
gint ctx;
gint ctx_cmds;
gint ctx_terms;
gint ctx_term;
} ett;
} gcp_hf_ett_t;
#define NULL_CONTEXT 0
#define CHOOSE_CONTEXT 0xFFFFFFFE
#define ALL_CONTEXTS 0xFFFFFFFF
typedef enum {
GCP_CMD_NONE,
GCP_CMD_ADD_REQ,
GCP_CMD_MOVE_REQ,
GCP_CMD_MOD_REQ,
GCP_CMD_SUB_REQ,
GCP_CMD_AUDITCAP_REQ,
GCP_CMD_AUDITVAL_REQ,
GCP_CMD_NOTIFY_REQ,
GCP_CMD_SVCCHG_REQ,
GCP_CMD_TOPOLOGY_REQ,
GCP_CMD_CTX_ATTR_AUDIT_REQ,
GCP_CMD_OTHER_REQ,
GCP_CMD_ADD_REPLY,
GCP_CMD_MOVE_REPLY,
GCP_CMD_MOD_REPLY,
GCP_CMD_SUB_REPLY,
GCP_CMD_AUDITCAP_REPLY,
GCP_CMD_AUDITVAL_REPLY,
GCP_CMD_NOTIFY_REPLY,
GCP_CMD_SVCCHG_REPLY,
GCP_CMD_TOPOLOGY_REPLY,
GCP_CMD_REPLY
} gcp_cmd_type_t;
typedef enum {
GCP_TRX_NONE,
GCP_TRX_REQUEST,
GCP_TRX_PENDING,
GCP_TRX_REPLY,
GCP_TRX_ACK
} gcp_trx_type_t;
typedef struct _gcp_msg_t {
guint32 lo_addr;
guint32 hi_addr;
guint32 framenum;
nstime_t time;
struct _gcp_trx_msg_t* trxs;
gboolean committed;
} gcp_msg_t;
typedef struct _gcp_trx_msg_t {
struct _gcp_trx_t* trx;
struct _gcp_trx_msg_t* next;
struct _gcp_trx_msg_t* last;
} gcp_trx_msg_t;
typedef struct _gcp_cmd_msg_t {
struct _gcp_cmd_t* cmd;
struct _gcp_cmd_msg_t* next;
struct _gcp_cmd_msg_t* last;
} gcp_cmd_msg_t;
typedef struct _gcp_trx_t {
gcp_msg_t* initial;
guint32 id;
gcp_trx_type_t type;
guint pendings;
struct _gcp_cmd_msg_t* cmds;
struct _gcp_trx_ctx_t* ctxs;
guint error;
} gcp_trx_t;
#define GCP_TERM_TYPE_UNKNOWN 0
#define GCP_TERM_TYPE_AAL1 1
#define GCP_TERM_TYPE_AAL2 2
#define GCP_TERM_TYPE_AAL1_STRUCT 3
#define GCP_TERM_TYPE_IP_RTP 4
#define GCP_TERM_TYPE_TDM 5
typedef enum _gcp_wildcard_t {
GCP_WILDCARD_NONE,
GCP_WILDCARD_CHOOSE,
GCP_WILDCARD_ALL
} gcp_wildcard_t;
typedef struct _gcp_term_t {
const gchar* str;
const guint8* buffer;
guint len;
guint type;
gchar* bir;
gchar* nsap;
gcp_msg_t* start;
} gcp_term_t;
typedef struct _gcp_terms_t {
gcp_term_t* term;
struct _gcp_terms_t* next;
struct _gcp_terms_t* last;
} gcp_terms_t;
typedef struct _gcp_cmd_t {
guint offset;
const gchar* str;
gcp_cmd_type_t type;
gcp_terms_t terms;
struct _gcp_msg_t* msg;
struct _gcp_trx_t* trx;
struct _gcp_ctx_t* ctx;
guint error;
} gcp_cmd_t;
typedef struct _gcp_ctx_t {
gcp_msg_t* initial;
guint32 id;
struct _gcp_cmd_msg_t* cmds;
struct _gcp_ctx_t* prev;
gcp_terms_t terms;
} gcp_ctx_t;
extern gcp_msg_t* gcp_msg(packet_info* pinfo, int o, gboolean persistent);
extern gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean persistent);
extern gcp_ctx_t* gcp_ctx(gcp_msg_t* m, gcp_trx_t* t, guint32 c_id, gboolean persistent);
extern gcp_cmd_t* gcp_cmd(gcp_msg_t* m, gcp_trx_t* t, gcp_ctx_t* c, gcp_cmd_type_t type, guint offset, gboolean persistent);
extern gcp_term_t* gcp_cmd_add_term(gcp_msg_t* m, gcp_trx_t* tr, gcp_cmd_t* c, gcp_term_t* t, gcp_wildcard_t wildcard, gboolean persistent);
extern void gcp_analyze_msg(proto_tree* gcp_tree, packet_info* pinfo, tvbuff_t* gcp_tvb, gcp_msg_t* m, gcp_hf_ett_t* ids, expert_field* command_err);
#define GCP_ETT_ARR_ELEMS(gi) &(gi.ett.ctx),&(gi.ett.ctx_cmds),&(gi.ett.ctx_terms),&(gi.ett.ctx_term)
#define GCP_HF_ARR_ELEMS(n,gi) \
{ &(gi.hf.ctx), { "Context", n ".ctx", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_term), { "Termination", n ".ctx.term", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_term_type), { "Type", n ".ctx.term.type", FT_UINT32, BASE_HEX, VALS(gcp_term_types), 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_term_bir), { "BIR", n ".ctx.term.bir", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_term_nsap), { "NSAP", n ".ctx.term.nsap", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_cmd), { "Command in Frame", n ".ctx.cmd", FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }}
WS_DLL_PUBLIC const value_string gcp_cmd_type[];
WS_DLL_PUBLIC const value_string gcp_term_types[];
extern const gchar* gcp_msg_to_str(gcp_msg_t* m, gboolean persistent);
#define gcp_cmd_set_error(c,e) (c->error = e)
#define gcp_trx_set_error(t,e) (t->error = e)
/* END Gateway Control Protocol -- Context Tracking */
typedef struct _h248_curr_info_t h248_curr_info_t;

View File

@ -33,10 +33,14 @@
#include "config.h"
#include <packet.h>
#include <epan/packet.h>
#include <epan/exceptions.h>
#include <epan/tap.h>
#include <epan/asn1.h>
#include <epan/prefs.h>
#include <epan/exported_pdu.h>
#include "packet-alcap.h"
#include "packet-ber.h"
#include "packet-tpkt.h"
#include "packet-mtp3.h"
#include "packet-h248.h"
@ -398,7 +402,7 @@ static int hf_h248_NotifyCompletion_otherReason = -1;
static int hf_h248_NotifyCompletion_onIteration = -1;
/*--- End of included file: packet-h248-hf.c ---*/
#line 75 "./asn1/h248/packet-h248-template.c"
#line 79 "./asn1/h248/packet-h248-template.c"
/* Initialize the subtree pointers */
static gint ett_h248 = -1;
@ -566,7 +570,7 @@ static gint ett_h248_EventParameterV1 = -1;
static gint ett_h248_SigParameterV1 = -1;
/*--- End of included file: packet-h248-ett.c ---*/
#line 95 "./asn1/h248/packet-h248-template.c"
#line 99 "./asn1/h248/packet-h248-template.c"
static expert_field ei_h248_errored_command = EI_INIT;
static expert_field ei_h248_transactionId64 = EI_INIT;
@ -575,10 +579,731 @@ static expert_field ei_h248_octet_string_expected = EI_INIT;
static dissector_table_t subdissector_table;
static wmem_tree_t* msgs = NULL;
static wmem_tree_t* trxs = NULL;
static wmem_tree_t* ctxs_by_trx = NULL;
static wmem_tree_t* ctxs = NULL;
/* Gateway Control Protocol -- Context Tracking */
const value_string gcp_cmd_type[] = {
{ GCP_CMD_NONE, "NoCommand"},
{ GCP_CMD_ADD_REQ, "addReq"},
{ GCP_CMD_MOVE_REQ, "moveReq"},
{ GCP_CMD_MOD_REQ, "modReq"},
{ GCP_CMD_SUB_REQ, "subtractReq"},
{ GCP_CMD_AUDITCAP_REQ, "auditCapRequest"},
{ GCP_CMD_AUDITVAL_REQ, "auditValueRequest"},
{ GCP_CMD_NOTIFY_REQ, "notifyReq"},
{ GCP_CMD_SVCCHG_REQ, "serviceChangeReq"},
{ GCP_CMD_TOPOLOGY_REQ, "topologyReq"},
{ GCP_CMD_CTX_ATTR_AUDIT_REQ, "ctxAttrAuditReq"},
{ GCP_CMD_ADD_REPLY, "addReply"},
{ GCP_CMD_MOVE_REPLY, "moveReply"},
{ GCP_CMD_MOD_REPLY, "modReply"},
{ GCP_CMD_SUB_REPLY, "subtractReply"},
{ GCP_CMD_AUDITCAP_REPLY, "auditCapReply"},
{ GCP_CMD_AUDITVAL_REPLY, "auditValReply"},
{ GCP_CMD_NOTIFY_REPLY, "notifyReply"},
{ GCP_CMD_SVCCHG_REPLY, "serviceChangeReply"},
{ GCP_CMD_TOPOLOGY_REPLY, "topologyReply"},
{ 0, NULL }
};
const value_string gcp_term_types[] = {
{ GCP_TERM_TYPE_AAL1, "aal1" },
{ GCP_TERM_TYPE_AAL2, "aal2" },
{ GCP_TERM_TYPE_AAL1_STRUCT, "aal1struct" },
{ GCP_TERM_TYPE_IP_RTP, "ipRtp" },
{ GCP_TERM_TYPE_TDM, "tdm" },
{ 0, NULL }
};
static wmem_tree_t* gcp_msgs = NULL;
static wmem_tree_t* gcp_trxs = NULL;
static wmem_tree_t* gcp_ctxs_by_trx = NULL;
static wmem_tree_t* gcp_ctxs = NULL;
gcp_msg_t* gcp_msg(packet_info* pinfo, int o, gboolean keep_persistent_data) {
gcp_msg_t* m;
guint32 framenum = (guint32)pinfo->num;
guint32 offset = (guint32)o;
address* src = &(pinfo->src);
address* dst = &(pinfo->dst);
address* lo_addr;
address* hi_addr;
if (keep_persistent_data) {
wmem_tree_key_t key[3];
key[0].length = 1;
key[0].key = &(framenum);
key[1].length = 1;
key[1].key = &offset;
key[2].length = 0;
key[2].key =NULL;
if (( m = (gcp_msg_t *)wmem_tree_lookup32_array(gcp_msgs,key) )) {
m->committed = TRUE;
return m;
} else {
m = wmem_new(wmem_file_scope(), gcp_msg_t);
m->framenum = framenum;
m->time = pinfo->abs_ts;
m->trxs = NULL;
m->committed = FALSE;
wmem_tree_insert32_array(gcp_msgs,key,m);
}
} else {
m = wmem_new0(wmem_packet_scope(), gcp_msg_t);
m->framenum = framenum;
m->trxs = NULL;
m->committed = FALSE;
}
if (cmp_address(src, dst) < 0) {
lo_addr = src;
hi_addr = dst;
} else {
lo_addr = dst;
hi_addr = src;
}
switch(lo_addr->type) {
case AT_NONE:
m->lo_addr = 0;
m->hi_addr = 0;
break;
case AT_IPv4:
memcpy((guint8*)&(m->hi_addr),hi_addr->data,4);
memcpy((guint8*)&(m->lo_addr),lo_addr->data,4);
break;
case AT_SS7PC:
m->hi_addr = mtp3_pc_hash((const mtp3_addr_pc_t *)hi_addr->data);
m->lo_addr = mtp3_pc_hash((const mtp3_addr_pc_t *)lo_addr->data);
break;
default:
/* XXX: heuristic and error prone */
m->hi_addr = g_str_hash(address_to_str(wmem_packet_scope(), hi_addr));
m->lo_addr = g_str_hash(address_to_str(wmem_packet_scope(), lo_addr));
break;
}
return m;
}
gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean keep_persistent_data) {
gcp_trx_t* t = NULL;
gcp_trx_msg_t* trxmsg;
if ( !m ) return NULL;
if (keep_persistent_data) {
if (m->committed) {
for ( trxmsg = m->trxs; trxmsg; trxmsg = trxmsg->next) {
if (trxmsg->trx && trxmsg->trx->id == t_id) {
return trxmsg->trx;
}
}
DISSECTOR_ASSERT_NOT_REACHED();
} else {
wmem_tree_key_t key[4];
key[0].length = 1;
key[0].key = &(m->hi_addr);
key[1].length = 1;
key[1].key = &(m->lo_addr);
key[2].length = 1;
key[2].key = &(t_id);
key[3].length = 0;
key[3].key = NULL;
trxmsg = wmem_new(wmem_file_scope(), gcp_trx_msg_t);
t = (gcp_trx_t *)wmem_tree_lookup32_array(gcp_trxs,key);
if (!t) {
t = wmem_new(wmem_file_scope(), gcp_trx_t);
t->initial = m;
t->id = t_id;
t->type = type;
t->pendings = 0;
t->error = 0;
t->cmds = NULL;
wmem_tree_insert32_array(gcp_trxs,key,t);
}
/* XXX: request, reply and ack + point to frames where they are */
switch ( type ) {
case GCP_TRX_PENDING:
t->pendings++;
break;
default:
break;
}
}
} else {
t = wmem_new(wmem_packet_scope(), gcp_trx_t);
trxmsg = wmem_new(wmem_packet_scope(), gcp_trx_msg_t);
t->initial = NULL;
t->id = t_id;
t->type = type;
t->pendings = 0;
t->error = 0;
t->cmds = NULL;
}
DISSECTOR_ASSERT(trxmsg);
trxmsg->trx = t;
trxmsg->next = NULL;
trxmsg->last = trxmsg;
if (m->trxs) {
m->trxs->last = m->trxs->last->next = trxmsg;
} else {
m->trxs = trxmsg;
}
return t;
}
gcp_ctx_t* gcp_ctx(gcp_msg_t* m, gcp_trx_t* t, guint32 c_id, gboolean persistent) {
gcp_ctx_t* context = NULL;
gcp_ctx_t** context_p = NULL;
if ( !m || !t ) return NULL;
if (persistent) {
wmem_tree_key_t ctx_key[4];
wmem_tree_key_t trx_key[4];
ctx_key[0].length = 1;
ctx_key[0].key = &(m->hi_addr);
ctx_key[1].length = 1;
ctx_key[1].key = &(m->lo_addr);
ctx_key[2].length = 1;
ctx_key[2].key = &(c_id);
ctx_key[3].length = 0;
ctx_key[3].key = NULL;
trx_key[0].length = 1;
trx_key[0].key = &(m->hi_addr);
trx_key[1].length = 1;
trx_key[1].key = &(m->lo_addr);
trx_key[2].length = 1;
trx_key[2].key = &(t->id);
trx_key[3].length = 0;
trx_key[3].key = NULL;
if (m->committed) {
if (( context = (gcp_ctx_t *)wmem_tree_lookup32_array(gcp_ctxs_by_trx,trx_key) )) {
return context;
} if ((context_p = (gcp_ctx_t **)wmem_tree_lookup32_array(gcp_ctxs,ctx_key))) {
context = *context_p;
do {
if (context->initial->framenum <= m->framenum) {
return context;
}
} while(( context = context->prev ));
DISSECTOR_ASSERT(! "a context should exist");
}
} else {
if (c_id == CHOOSE_CONTEXT) {
if (! ( context = (gcp_ctx_t *)wmem_tree_lookup32_array(gcp_ctxs_by_trx,trx_key))) {
context = wmem_new(wmem_file_scope(), gcp_ctx_t);
context->initial = m;
context->cmds = NULL;
context->id = c_id;
context->terms.last = &(context->terms);
context->terms.next = NULL;
context->terms.term = NULL;
wmem_tree_insert32_array(gcp_ctxs_by_trx,trx_key,context);
}
} else {
if (( context = (gcp_ctx_t *)wmem_tree_lookup32_array(gcp_ctxs_by_trx,trx_key) )) {
if (( context_p = (gcp_ctx_t **)wmem_tree_lookup32_array(gcp_ctxs,ctx_key) )) {
if (context != *context_p) {
if(context->id != CHOOSE_CONTEXT) {
context = wmem_new(wmem_file_scope(), gcp_ctx_t);
}
context->initial = m;
context->id = c_id;
context->cmds = NULL;
context->terms.last = &(context->terms);
context->terms.next = NULL;
context->terms.term = NULL;
context->prev = *context_p;
*context_p = context;
}
} else {
context_p = wmem_new(wmem_file_scope(), gcp_ctx_t*);
*context_p = context;
context->initial = m;
context->id = c_id;
wmem_tree_insert32_array(gcp_ctxs,ctx_key,context_p);
}
} else if (! ( context_p = (gcp_ctx_t**)wmem_tree_lookup32_array(gcp_ctxs,ctx_key) )) {
context = wmem_new(wmem_file_scope(), gcp_ctx_t);
context->initial = m;
context->id = c_id;
context->cmds = NULL;
context->terms.last = &(context->terms);
context->terms.next = NULL;
context->terms.term = NULL;
context_p = wmem_new(wmem_file_scope(), gcp_ctx_t*);
*context_p = context;
wmem_tree_insert32_array(gcp_ctxs,ctx_key,context_p);
} else {
context = *context_p;
}
}
}
} else {
context = wmem_new(wmem_packet_scope(), gcp_ctx_t);
context->initial = m;
context->cmds = NULL;
context->id = c_id;
context->terms.last = &(context->terms);
context->terms.next = NULL;
context->terms.term = NULL;
}
return context;
}
gcp_cmd_t* gcp_cmd(gcp_msg_t* m, gcp_trx_t* t, gcp_ctx_t* c, gcp_cmd_type_t type, guint offset, gboolean persistent) {
gcp_cmd_t* cmd;
gcp_cmd_msg_t* cmdtrx;
gcp_cmd_msg_t* cmdctx;
if ( !m || !t || !c ) return NULL;
if (persistent) {
if (m->committed) {
DISSECTOR_ASSERT(t->cmds != NULL);
for (cmdctx = t->cmds; cmdctx; cmdctx = cmdctx->next) {
cmd = cmdctx->cmd;
if (cmd->msg == m && cmd->offset == offset) {
return cmd;
}
}
DISSECTOR_ASSERT(!"called for a command that does not exist!");
return NULL;
} else {
cmd = wmem_new(wmem_file_scope(), gcp_cmd_t);
cmdtrx = wmem_new(wmem_file_scope(), gcp_cmd_msg_t);
cmdctx = wmem_new(wmem_file_scope(), gcp_cmd_msg_t);
}
} else {
cmd = wmem_new(wmem_packet_scope(), gcp_cmd_t);
cmdtrx = wmem_new(wmem_packet_scope(), gcp_cmd_msg_t);
cmdctx = wmem_new(wmem_packet_scope(), gcp_cmd_msg_t);
}
cmd->type = type;
cmd->offset = offset;
cmd->terms.term = NULL;
cmd->terms.next = NULL;
cmd->terms.last = &(cmd->terms);
cmd->str = NULL;
cmd->msg = m;
if ((type != GCP_CMD_NONE) && (!persistent)){
cmd->str = val_to_str_const(type, gcp_cmd_type, "Unknown");
}
cmd->trx = t;
cmd->ctx = c;
cmd->error = 0;
cmdctx->cmd = cmdtrx->cmd = cmd;
cmdctx->next = cmdtrx->next = NULL;
cmdctx->last = cmdtrx->last = NULL;
if (t->cmds) {
t->cmds->last->next = cmdtrx;
t->cmds->last = cmdtrx;
} else {
t->cmds = cmdtrx;
t->cmds->last = cmdtrx;
}
if (c->cmds) {
c->cmds->last->next = cmdctx;
c->cmds->last = cmdctx;
} else {
c->cmds = cmdctx;
c->cmds->last = cmdctx;
}
return cmd;
}
gcp_term_t* gcp_cmd_add_term(gcp_msg_t* m, gcp_trx_t* tr, gcp_cmd_t* c, gcp_term_t* t, gcp_wildcard_t wildcard, gboolean persistent) {
gcp_terms_t* ct;
gcp_terms_t* ct2;
static gcp_term_t all_terms = {"$",(const guint8*)"",1,GCP_TERM_TYPE_UNKNOWN,NULL,NULL,NULL};
if ( !c ) return NULL;
if ( wildcard == GCP_WILDCARD_CHOOSE) {
return &all_terms;
}
if (persistent) {
if ( c->msg->committed ) {
if (wildcard == GCP_WILDCARD_ALL) {
for (ct = c->ctx->terms.next; ct; ct = ct->next) {
/* XXX not handling more wilcards in one msg */
if ( ct->term->start == m ) {
return ct->term;
}
}
return NULL;
} else {
for (ct = c->ctx->terms.next; ct; ct = ct->next) {
if ( g_str_equal(ct->term->str,t->str) ) {
return ct->term;
}
}
return NULL;
}
} else {
for (ct = c->ctx->terms.next; ct; ct = ct->next) {
if ( g_str_equal(ct->term->str,t->str) || ct->term->start == m) {
break;
}
}
if ( ! ct ) {
if (wildcard == GCP_WILDCARD_ALL) {
ct = wmem_new(wmem_file_scope(), gcp_terms_t);
ct->next = NULL;
ct->term = wmem_new0(wmem_file_scope(), gcp_term_t);
ct->term->start = m;
ct->term->str = "*";
ct->term->buffer = NULL;
ct->term->len = 0;
c->terms.last = c->terms.last->next = ct;
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->ctx->terms.last->next = ct2;
c->ctx->terms.last = ct2;
return ct->term;
} else {
for (ct = c->ctx->terms.next; ct; ct = ct->next) {
/* XXX not handling more wilcards in one msg */
if ( ct->term->buffer == NULL && tr->cmds->cmd->msg == ct->term->start ) {
ct->term->str = wmem_strdup(wmem_file_scope(), t->str);
ct->term->buffer = (const guint8 *)wmem_memdup(wmem_file_scope(), t->buffer,t->len);
ct->term->len = t->len;
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->terms.last = c->terms.last->next = ct2;
return ct->term;
}
if ( g_str_equal(ct->term->str,t->str) ) {
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->terms.last = c->terms.last->next = ct2;
return ct->term;
}
}
ct = wmem_new(wmem_file_scope(), gcp_terms_t);
ct->next = NULL;
ct->term = wmem_new0(wmem_file_scope(), gcp_term_t);
ct->term->start = m;
ct->term->str = wmem_strdup(wmem_file_scope(), t->str);
ct->term->buffer = (const guint8 *)wmem_memdup(wmem_file_scope(), t->buffer,t->len);
ct->term->len = t->len;
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->terms.last = c->terms.last->next = ct2;
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->ctx->terms.last = c->ctx->terms.last->next = ct2;
return ct->term;
}
} else {
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->terms.last = c->terms.last->next = ct2;
return ct->term;
}
DISSECTOR_ASSERT_NOT_REACHED();
}
} else {
ct = wmem_new(wmem_packet_scope(), gcp_terms_t);
ct->term = t;
ct->next = NULL;
c->terms.last = c->terms.last->next = ct;
return t;
}
}
static const gchar* gcp_cmd_to_str(gcp_cmd_t* c, gboolean persistent) {
const gchar* s;
gcp_terms_t* term;
if ( !c ) return "-";
switch (c->type) {
case GCP_CMD_NONE:
return "-";
break;
case GCP_CMD_ADD_REQ:
s = "AddReq {";
break;
case GCP_CMD_MOVE_REQ:
s = "MoveReq {";
break;
case GCP_CMD_MOD_REQ:
s = "ModReq {";
break;
case GCP_CMD_SUB_REQ:
s = "SubReq {";
break;
case GCP_CMD_AUDITCAP_REQ:
s = "AuditCapReq {";
break;
case GCP_CMD_AUDITVAL_REQ:
s = "AuditValReq {";
break;
case GCP_CMD_NOTIFY_REQ:
s = "NotifyReq {";
break;
case GCP_CMD_SVCCHG_REQ:
s = "SvcChgReq {";
break;
case GCP_CMD_TOPOLOGY_REQ:
s = "TopologyReq {";
break;
case GCP_CMD_CTX_ATTR_AUDIT_REQ:
s = "CtxAttribAuditReq {";
break;
case GCP_CMD_ADD_REPLY:
s = "AddReply {";
break;
case GCP_CMD_MOVE_REPLY:
s = "MoveReply {";
break;
case GCP_CMD_MOD_REPLY:
s = "ModReply {";
break;
case GCP_CMD_SUB_REPLY:
s = "SubReply {";
break;
case GCP_CMD_AUDITCAP_REPLY:
s = "AuditCapReply {";
break;
case GCP_CMD_AUDITVAL_REPLY:
s = "AuditValReply {";
break;
case GCP_CMD_NOTIFY_REPLY:
s = "NotifyReply {";
break;
case GCP_CMD_SVCCHG_REPLY:
s = "SvcChgReply {";
break;
case GCP_CMD_TOPOLOGY_REPLY:
s = "TopologyReply {";
break;
case GCP_CMD_REPLY:
s = "ActionReply {";
break;
case GCP_CMD_OTHER_REQ:
s = "Request {";
break;
default:
s = "-";
break;
}
for (term = c->terms.next; term; term = term->next) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,term->term->str);
}
if (c->error) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s Error=%i",s,c->error);
}
s = wmem_strdup_printf(wmem_packet_scope(), "%s }", s);
if (persistent) {
if (! c->str) c->str = wmem_strdup(wmem_file_scope(), s);
} else {
c->str = s;
}
return s;
}
static const gchar* gcp_trx_to_str(gcp_msg_t* m, gcp_trx_t* t, gboolean persistent) {
gchar* s;
gcp_cmd_msg_t* c;
if ( !m || !t ) return "-";
s = wmem_strdup_printf(wmem_packet_scope(), "T %x { ",t->id);
if (t->cmds) {
if (t->cmds->cmd->ctx) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s C %x {",s,t->cmds->cmd->ctx->id);
for (c = t->cmds; c; c = c->next) {
if (c->cmd->msg == m) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,gcp_cmd_to_str(c->cmd,persistent));
}
}
s = wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,"}");
}
}
if (t->error) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s Error=%i",s,t->error);
}
return wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,"}");
}
const gchar* gcp_msg_to_str(gcp_msg_t* m, gboolean persistent) {
gcp_trx_msg_t* t;
const gchar* s = "";
if ( !m ) return "-";
for (t = m->trxs; t; t = t->next) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,gcp_trx_to_str(m,t->trx, persistent));
}
return s;
}
typedef struct _gcp_ctxs_t {
struct _gcp_ctx_t* ctx;
struct _gcp_ctxs_t* next;
} gcp_ctxs_t;
/*static const gchar* trx_types[] = {"None","Req","Reply","Pending","Ack"};*/
void gcp_analyze_msg(proto_tree* gcp_tree, packet_info* pinfo, tvbuff_t* gcp_tvb, gcp_msg_t* m, gcp_hf_ett_t* ids, expert_field* command_err) {
gcp_trx_msg_t* t;
gcp_ctxs_t contexts = {NULL,NULL};
gcp_ctxs_t* ctx_node;
gcp_cmd_msg_t* c;
for (t = m->trxs; t; t = t->next) {
for (c = t->trx->cmds; c; c = c->next) {
gcp_ctx_t* ctx = c->cmd->ctx;
for (ctx_node = contexts.next; ctx_node; ctx_node = ctx_node->next) {
if (ctx_node->ctx->id == ctx->id) {
break;
}
}
if (! ctx_node) {
ctx_node = wmem_new(wmem_packet_scope(), gcp_ctxs_t);
ctx_node->ctx = ctx;
ctx_node->next = contexts.next;
contexts.next = ctx_node;
}
}
}
for (ctx_node = contexts.next; ctx_node; ctx_node = ctx_node->next) {
gcp_ctx_t* ctx = ctx_node->ctx;
proto_item* ctx_item = proto_tree_add_uint(gcp_tree,ids->hf.ctx,gcp_tvb,0,0,ctx->id);
proto_tree* ctx_tree = proto_item_add_subtree(ctx_item,ids->ett.ctx);
gcp_terms_t *ctx_term;
PROTO_ITEM_SET_GENERATED(ctx_item);
if (ctx->cmds) {
proto_tree* history_tree = proto_tree_add_subtree(ctx_tree,gcp_tvb,0,0,ids->ett.ctx_cmds,NULL,"[ Command History ]");
for (c = ctx->cmds; c; c = c->next) {
proto_item* cmd_item = proto_tree_add_uint(history_tree,ids->hf.ctx_cmd,gcp_tvb,0,0,c->cmd->msg->framenum);
if (c->cmd->str) proto_item_append_text(cmd_item," %s ",c->cmd->str);
PROTO_ITEM_SET_GENERATED(cmd_item);
if (c->cmd->error) {
expert_add_info(pinfo, cmd_item, command_err);
}
}
}
if (( ctx_term = ctx->terms.next )) {
proto_tree* terms_tree = proto_tree_add_subtree(ctx_tree,gcp_tvb,0,0,ids->ett.ctx_terms,NULL,"[ Terminations Used ]");
for (; ctx_term; ctx_term = ctx_term->next ) {
if ( ctx_term->term && ctx_term->term->str) {
proto_item* pi = proto_tree_add_string(terms_tree,ids->hf.ctx_term,gcp_tvb,0,0,ctx_term->term->str);
proto_tree* term_tree = proto_item_add_subtree(pi,ids->ett.ctx_term);
PROTO_ITEM_SET_GENERATED(pi);
if (ctx_term->term->type) {
pi = proto_tree_add_uint(term_tree,ids->hf.ctx_term_type,gcp_tvb,0,0,ctx_term->term->type);
PROTO_ITEM_SET_GENERATED(pi);
}
if (ctx_term->term->bir) {
pi = proto_tree_add_string(term_tree,ids->hf.ctx_term_bir,gcp_tvb,0,0,ctx_term->term->bir);
PROTO_ITEM_SET_GENERATED(pi);
}
if (ctx_term->term->nsap) {
pi = proto_tree_add_string(term_tree,ids->hf.ctx_term_nsap,gcp_tvb,0,0,ctx_term->term->nsap);
PROTO_ITEM_SET_GENERATED(pi);
}
if (ctx_term->term->bir && ctx_term->term->nsap) {
gchar* tmp_key = wmem_strdup_printf(wmem_packet_scope(), "%s:%s",ctx_term->term->nsap,ctx_term->term->bir);
gchar* key = g_ascii_strdown(tmp_key, -1);
alcap_tree_from_bearer_key(term_tree, gcp_tvb, pinfo, key);
g_free(key);
}
}
}
}
}
}
/* END Gateway Control Protocol -- Context Tracking */
static gboolean keep_persistent_data = FALSE;
static guint global_udp_port = 2945;
@ -5365,7 +6090,7 @@ dissect_h248_SigParameterV1(gboolean implicit_tag _U_, tvbuff_t *tvb _U_, int of
/*--- End of included file: packet-h248-fn.c ---*/
#line 1443 "./asn1/h248/packet-h248-template.c"
#line 2168 "./asn1/h248/packet-h248-template.c"
static int dissect_h248_tpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
dissect_tpkt_encap(tvb, pinfo, tree, h248_desegment, h248_handle);
@ -6791,7 +7516,7 @@ void proto_register_h248(void) {
NULL, HFILL }},
/*--- End of included file: packet-h248-hfarr.c ---*/
#line 1612 "./asn1/h248/packet-h248-template.c"
#line 2337 "./asn1/h248/packet-h248-template.c"
GCP_HF_ARR_ELEMS("h248",h248_arrel)
@ -6957,7 +7682,7 @@ void proto_register_h248(void) {
&ett_h248_SigParameterV1,
/*--- End of included file: packet-h248-ettarr.c ---*/
#line 1630 "./asn1/h248/packet-h248-template.c"
#line 2355 "./asn1/h248/packet-h248-template.c"
};
static ei_register_info ei[] = {
@ -7003,14 +7728,12 @@ void proto_register_h248(void) {
"Desegment H.248 messages that span more TCP segments",
&h248_desegment);
msgs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
trxs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
ctxs_by_trx = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
ctxs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
gcp_msgs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
gcp_trxs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
gcp_ctxs_by_trx = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
gcp_ctxs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
h248_tap = register_tap("h248");
gcp_init();
}
/*--- proto_reg_handoff_h248 -------------------------------------------*/

View File

@ -32,10 +32,183 @@
*/
#ifndef PACKET_H248_H
#define PACKET_H248_H
#include <epan/gcp.h>
#include "ws_symbol_export.h"
/*#include "packet-h248-exp.h"*/
#include <epan/packet.h>
#include <epan/expert.h>
#include <wsutil/nstime.h>
/* Gateway Control Protocol -- Context Tracking */
typedef struct _gcp_hf_ett_t {
struct {
int ctx;
int ctx_cmd;
int ctx_term;
int ctx_term_type;
int ctx_term_bir;
int ctx_term_nsap;
} hf;
struct {
gint ctx;
gint ctx_cmds;
gint ctx_terms;
gint ctx_term;
} ett;
} gcp_hf_ett_t;
#define NULL_CONTEXT 0
#define CHOOSE_CONTEXT 0xFFFFFFFE
#define ALL_CONTEXTS 0xFFFFFFFF
typedef enum {
GCP_CMD_NONE,
GCP_CMD_ADD_REQ,
GCP_CMD_MOVE_REQ,
GCP_CMD_MOD_REQ,
GCP_CMD_SUB_REQ,
GCP_CMD_AUDITCAP_REQ,
GCP_CMD_AUDITVAL_REQ,
GCP_CMD_NOTIFY_REQ,
GCP_CMD_SVCCHG_REQ,
GCP_CMD_TOPOLOGY_REQ,
GCP_CMD_CTX_ATTR_AUDIT_REQ,
GCP_CMD_OTHER_REQ,
GCP_CMD_ADD_REPLY,
GCP_CMD_MOVE_REPLY,
GCP_CMD_MOD_REPLY,
GCP_CMD_SUB_REPLY,
GCP_CMD_AUDITCAP_REPLY,
GCP_CMD_AUDITVAL_REPLY,
GCP_CMD_NOTIFY_REPLY,
GCP_CMD_SVCCHG_REPLY,
GCP_CMD_TOPOLOGY_REPLY,
GCP_CMD_REPLY
} gcp_cmd_type_t;
typedef enum {
GCP_TRX_NONE,
GCP_TRX_REQUEST,
GCP_TRX_PENDING,
GCP_TRX_REPLY,
GCP_TRX_ACK
} gcp_trx_type_t;
typedef struct _gcp_msg_t {
guint32 lo_addr;
guint32 hi_addr;
guint32 framenum;
nstime_t time;
struct _gcp_trx_msg_t* trxs;
gboolean committed;
} gcp_msg_t;
typedef struct _gcp_trx_msg_t {
struct _gcp_trx_t* trx;
struct _gcp_trx_msg_t* next;
struct _gcp_trx_msg_t* last;
} gcp_trx_msg_t;
typedef struct _gcp_cmd_msg_t {
struct _gcp_cmd_t* cmd;
struct _gcp_cmd_msg_t* next;
struct _gcp_cmd_msg_t* last;
} gcp_cmd_msg_t;
typedef struct _gcp_trx_t {
gcp_msg_t* initial;
guint32 id;
gcp_trx_type_t type;
guint pendings;
struct _gcp_cmd_msg_t* cmds;
struct _gcp_trx_ctx_t* ctxs;
guint error;
} gcp_trx_t;
#define GCP_TERM_TYPE_UNKNOWN 0
#define GCP_TERM_TYPE_AAL1 1
#define GCP_TERM_TYPE_AAL2 2
#define GCP_TERM_TYPE_AAL1_STRUCT 3
#define GCP_TERM_TYPE_IP_RTP 4
#define GCP_TERM_TYPE_TDM 5
typedef enum _gcp_wildcard_t {
GCP_WILDCARD_NONE,
GCP_WILDCARD_CHOOSE,
GCP_WILDCARD_ALL
} gcp_wildcard_t;
typedef struct _gcp_term_t {
const gchar* str;
const guint8* buffer;
guint len;
guint type;
gchar* bir;
gchar* nsap;
gcp_msg_t* start;
} gcp_term_t;
typedef struct _gcp_terms_t {
gcp_term_t* term;
struct _gcp_terms_t* next;
struct _gcp_terms_t* last;
} gcp_terms_t;
typedef struct _gcp_cmd_t {
guint offset;
const gchar* str;
gcp_cmd_type_t type;
gcp_terms_t terms;
struct _gcp_msg_t* msg;
struct _gcp_trx_t* trx;
struct _gcp_ctx_t* ctx;
guint error;
} gcp_cmd_t;
typedef struct _gcp_ctx_t {
gcp_msg_t* initial;
guint32 id;
struct _gcp_cmd_msg_t* cmds;
struct _gcp_ctx_t* prev;
gcp_terms_t terms;
} gcp_ctx_t;
extern gcp_msg_t* gcp_msg(packet_info* pinfo, int o, gboolean persistent);
extern gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean persistent);
extern gcp_ctx_t* gcp_ctx(gcp_msg_t* m, gcp_trx_t* t, guint32 c_id, gboolean persistent);
extern gcp_cmd_t* gcp_cmd(gcp_msg_t* m, gcp_trx_t* t, gcp_ctx_t* c, gcp_cmd_type_t type, guint offset, gboolean persistent);
extern gcp_term_t* gcp_cmd_add_term(gcp_msg_t* m, gcp_trx_t* tr, gcp_cmd_t* c, gcp_term_t* t, gcp_wildcard_t wildcard, gboolean persistent);
extern void gcp_analyze_msg(proto_tree* gcp_tree, packet_info* pinfo, tvbuff_t* gcp_tvb, gcp_msg_t* m, gcp_hf_ett_t* ids, expert_field* command_err);
#define GCP_ETT_ARR_ELEMS(gi) &(gi.ett.ctx),&(gi.ett.ctx_cmds),&(gi.ett.ctx_terms),&(gi.ett.ctx_term)
#define GCP_HF_ARR_ELEMS(n,gi) \
{ &(gi.hf.ctx), { "Context", n ".ctx", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_term), { "Termination", n ".ctx.term", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_term_type), { "Type", n ".ctx.term.type", FT_UINT32, BASE_HEX, VALS(gcp_term_types), 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_term_bir), { "BIR", n ".ctx.term.bir", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_term_nsap), { "NSAP", n ".ctx.term.nsap", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_cmd), { "Command in Frame", n ".ctx.cmd", FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }}
WS_DLL_PUBLIC const value_string gcp_cmd_type[];
WS_DLL_PUBLIC const value_string gcp_term_types[];
extern const gchar* gcp_msg_to_str(gcp_msg_t* m, gboolean persistent);
#define gcp_cmd_set_error(c,e) (c->error = e)
#define gcp_trx_set_error(t,e) (t->error = e)
/* END Gateway Control Protocol -- Context Tracking */
typedef struct _h248_curr_info_t h248_curr_info_t;

View File

@ -29,6 +29,7 @@
#include "config.h"
#include "glib.h"
#include "packet-h248.h"
void proto_register_h248_dot10(void);

View File

@ -25,6 +25,11 @@
#include "config.h"
#include <epan/packet.h>
#include <epan/asn1.h>
#include "packet-ber.h"
#include "packet-isup.h"
#include "packet-h248.h"
void proto_register_h248_3gpp(void);

View File

@ -25,7 +25,13 @@
#include "config.h"
#include <epan/packet.h>
#include <epan/exceptions.h>
#include <epan/asn1.h>
#include "packet-ber.h"
#include "packet-isup.h"
#include "packet-q931.h"
#include "packet-h248.h"
void proto_register_h248_annex_c(void);

View File

@ -27,6 +27,11 @@
#include "config.h"
#include <epan/packet.h>
#include <epan/asn1.h>
#include "packet-ber.h"
#include "packet-isup.h"
#include "packet-h248.h"
void proto_reg_handoff_q1950(void);

View File

@ -44,13 +44,17 @@
#include <epan/packet.h>
#include <epan/exceptions.h>
#include <epan/gcp.h>
#include <epan/tap.h>
#include <epan/rtd_table.h>
#include <epan/prefs.h>
#include <epan/prefs-int.h>
#include <epan/exported_pdu.h>
#include <epan/asn1.h>
#include <epan/sctpppids.h>
#include "packet-ber.h"
#include "packet-tpkt.h"
#include "packet-h245.h"
#include "packet-h248.h"
#include "packet-ip.h"
void proto_register_megaco(void);

View File

@ -1,782 +0,0 @@
/*
* gcp.c
* Gateway Control Protocol -- Context Tracking
*
* 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
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/*
* TO DO:
* - handle text-encoded termination wildcards adequtelly
* - avoid persistent tracking of NULL and ALL contexts
*/
#include "config.h"
#include "gcp.h"
static wmem_tree_t* msgs = NULL;
static wmem_tree_t* trxs = NULL;
static wmem_tree_t* ctxs_by_trx = NULL;
static wmem_tree_t* ctxs = NULL;
const value_string gcp_cmd_type[] = {
{ GCP_CMD_NONE, "NoCommand"},
{ GCP_CMD_ADD_REQ, "addReq"},
{ GCP_CMD_MOVE_REQ, "moveReq"},
{ GCP_CMD_MOD_REQ, "modReq"},
{ GCP_CMD_SUB_REQ, "subtractReq"},
{ GCP_CMD_AUDITCAP_REQ, "auditCapRequest"},
{ GCP_CMD_AUDITVAL_REQ, "auditValueRequest"},
{ GCP_CMD_NOTIFY_REQ, "notifyReq"},
{ GCP_CMD_SVCCHG_REQ, "serviceChangeReq"},
{ GCP_CMD_TOPOLOGY_REQ, "topologyReq"},
{ GCP_CMD_CTX_ATTR_AUDIT_REQ, "ctxAttrAuditReq"},
{ GCP_CMD_ADD_REPLY, "addReply"},
{ GCP_CMD_MOVE_REPLY, "moveReply"},
{ GCP_CMD_MOD_REPLY, "modReply"},
{ GCP_CMD_SUB_REPLY, "subtractReply"},
{ GCP_CMD_AUDITCAP_REPLY, "auditCapReply"},
{ GCP_CMD_AUDITVAL_REPLY, "auditValReply"},
{ GCP_CMD_NOTIFY_REPLY, "notifyReply"},
{ GCP_CMD_SVCCHG_REPLY, "serviceChangeReply"},
{ GCP_CMD_TOPOLOGY_REPLY, "topologyReply"},
{ 0, NULL }
};
const value_string gcp_term_types[] = {
{ GCP_TERM_TYPE_AAL1, "aal1" },
{ GCP_TERM_TYPE_AAL2, "aal2" },
{ GCP_TERM_TYPE_AAL1_STRUCT, "aal1struct" },
{ GCP_TERM_TYPE_IP_RTP, "ipRtp" },
{ GCP_TERM_TYPE_TDM, "tdm" },
{ 0, NULL }
};
void gcp_init(void) {
static gboolean gcp_initialized = FALSE;
if (gcp_initialized)
return;
msgs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
trxs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
ctxs_by_trx = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
ctxs = wmem_tree_new_autoreset(wmem_epan_scope(), wmem_file_scope());
gcp_initialized = TRUE;
}
gcp_msg_t* gcp_msg(packet_info* pinfo, int o, gboolean keep_persistent_data) {
gcp_msg_t* m;
guint32 framenum = (guint32)pinfo->num;
guint32 offset = (guint32)o;
address* src = &(pinfo->src);
address* dst = &(pinfo->dst);
address* lo_addr;
address* hi_addr;
if (keep_persistent_data) {
wmem_tree_key_t key[3];
key[0].length = 1;
key[0].key = &(framenum);
key[1].length = 1;
key[1].key = &offset;
key[2].length = 0;
key[2].key =NULL;
if (( m = (gcp_msg_t *)wmem_tree_lookup32_array(msgs,key) )) {
m->committed = TRUE;
return m;
} else {
m = wmem_new(wmem_file_scope(), gcp_msg_t);
m->framenum = framenum;
m->time = pinfo->abs_ts;
m->trxs = NULL;
m->committed = FALSE;
wmem_tree_insert32_array(msgs,key,m);
}
} else {
m = wmem_new0(wmem_packet_scope(), gcp_msg_t);
m->framenum = framenum;
m->trxs = NULL;
m->committed = FALSE;
}
if (cmp_address(src, dst) < 0) {
lo_addr = src;
hi_addr = dst;
} else {
lo_addr = dst;
hi_addr = src;
}
switch(lo_addr->type) {
case AT_NONE:
m->lo_addr = 0;
m->hi_addr = 0;
break;
case AT_IPv4:
memcpy((guint8*)&(m->hi_addr),hi_addr->data,4);
memcpy((guint8*)&(m->lo_addr),lo_addr->data,4);
break;
case AT_SS7PC:
m->hi_addr = mtp3_pc_hash((const mtp3_addr_pc_t *)hi_addr->data);
m->lo_addr = mtp3_pc_hash((const mtp3_addr_pc_t *)lo_addr->data);
break;
default:
/* XXX: heuristic and error prone */
m->hi_addr = g_str_hash(address_to_str(wmem_packet_scope(), hi_addr));
m->lo_addr = g_str_hash(address_to_str(wmem_packet_scope(), lo_addr));
break;
}
return m;
}
gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean keep_persistent_data) {
gcp_trx_t* t = NULL;
gcp_trx_msg_t* trxmsg;
if ( !m ) return NULL;
if (keep_persistent_data) {
if (m->committed) {
for ( trxmsg = m->trxs; trxmsg; trxmsg = trxmsg->next) {
if (trxmsg->trx && trxmsg->trx->id == t_id) {
return trxmsg->trx;
}
}
DISSECTOR_ASSERT_NOT_REACHED();
} else {
wmem_tree_key_t key[4];
key[0].length = 1;
key[0].key = &(m->hi_addr);
key[1].length = 1;
key[1].key = &(m->lo_addr);
key[2].length = 1;
key[2].key = &(t_id);
key[3].length = 0;
key[3].key = NULL;
trxmsg = wmem_new(wmem_file_scope(), gcp_trx_msg_t);
t = (gcp_trx_t *)wmem_tree_lookup32_array(trxs,key);
if (!t) {
t = wmem_new(wmem_file_scope(), gcp_trx_t);
t->initial = m;
t->id = t_id;
t->type = type;
t->pendings = 0;
t->error = 0;
t->cmds = NULL;
wmem_tree_insert32_array(trxs,key,t);
}
/* XXX: request, reply and ack + point to frames where they are */
switch ( type ) {
case GCP_TRX_PENDING:
t->pendings++;
break;
default:
break;
}
}
} else {
t = wmem_new(wmem_packet_scope(), gcp_trx_t);
trxmsg = wmem_new(wmem_packet_scope(), gcp_trx_msg_t);
t->initial = NULL;
t->id = t_id;
t->type = type;
t->pendings = 0;
t->error = 0;
t->cmds = NULL;
}
DISSECTOR_ASSERT(trxmsg);
trxmsg->trx = t;
trxmsg->next = NULL;
trxmsg->last = trxmsg;
if (m->trxs) {
m->trxs->last = m->trxs->last->next = trxmsg;
} else {
m->trxs = trxmsg;
}
return t;
}
gcp_ctx_t* gcp_ctx(gcp_msg_t* m, gcp_trx_t* t, guint32 c_id, gboolean persistent) {
gcp_ctx_t* context = NULL;
gcp_ctx_t** context_p = NULL;
if ( !m || !t ) return NULL;
if (persistent) {
wmem_tree_key_t ctx_key[4];
wmem_tree_key_t trx_key[4];
ctx_key[0].length = 1;
ctx_key[0].key = &(m->hi_addr);
ctx_key[1].length = 1;
ctx_key[1].key = &(m->lo_addr);
ctx_key[2].length = 1;
ctx_key[2].key = &(c_id);
ctx_key[3].length = 0;
ctx_key[3].key = NULL;
trx_key[0].length = 1;
trx_key[0].key = &(m->hi_addr);
trx_key[1].length = 1;
trx_key[1].key = &(m->lo_addr);
trx_key[2].length = 1;
trx_key[2].key = &(t->id);
trx_key[3].length = 0;
trx_key[3].key = NULL;
if (m->committed) {
if (( context = (gcp_ctx_t *)wmem_tree_lookup32_array(ctxs_by_trx,trx_key) )) {
return context;
} if ((context_p = (gcp_ctx_t **)wmem_tree_lookup32_array(ctxs,ctx_key))) {
context = *context_p;
do {
if (context->initial->framenum <= m->framenum) {
return context;
}
} while(( context = context->prev ));
DISSECTOR_ASSERT(! "a context should exist");
}
} else {
if (c_id == CHOOSE_CONTEXT) {
if (! ( context = (gcp_ctx_t *)wmem_tree_lookup32_array(ctxs_by_trx,trx_key))) {
context = wmem_new(wmem_file_scope(), gcp_ctx_t);
context->initial = m;
context->cmds = NULL;
context->id = c_id;
context->terms.last = &(context->terms);
context->terms.next = NULL;
context->terms.term = NULL;
wmem_tree_insert32_array(ctxs_by_trx,trx_key,context);
}
} else {
if (( context = (gcp_ctx_t *)wmem_tree_lookup32_array(ctxs_by_trx,trx_key) )) {
if (( context_p = (gcp_ctx_t **)wmem_tree_lookup32_array(ctxs,ctx_key) )) {
if (context != *context_p) {
if(context->id != CHOOSE_CONTEXT) {
context = wmem_new(wmem_file_scope(), gcp_ctx_t);
}
context->initial = m;
context->id = c_id;
context->cmds = NULL;
context->terms.last = &(context->terms);
context->terms.next = NULL;
context->terms.term = NULL;
context->prev = *context_p;
*context_p = context;
}
} else {
context_p = wmem_new(wmem_file_scope(), gcp_ctx_t*);
*context_p = context;
context->initial = m;
context->id = c_id;
wmem_tree_insert32_array(ctxs,ctx_key,context_p);
}
} else if (! ( context_p = (gcp_ctx_t**)wmem_tree_lookup32_array(ctxs,ctx_key) )) {
context = wmem_new(wmem_file_scope(), gcp_ctx_t);
context->initial = m;
context->id = c_id;
context->cmds = NULL;
context->terms.last = &(context->terms);
context->terms.next = NULL;
context->terms.term = NULL;
context_p = wmem_new(wmem_file_scope(), gcp_ctx_t*);
*context_p = context;
wmem_tree_insert32_array(ctxs,ctx_key,context_p);
} else {
context = *context_p;
}
}
}
} else {
context = wmem_new(wmem_packet_scope(), gcp_ctx_t);
context->initial = m;
context->cmds = NULL;
context->id = c_id;
context->terms.last = &(context->terms);
context->terms.next = NULL;
context->terms.term = NULL;
}
return context;
}
gcp_cmd_t* gcp_cmd(gcp_msg_t* m, gcp_trx_t* t, gcp_ctx_t* c, gcp_cmd_type_t type, guint offset, gboolean persistent) {
gcp_cmd_t* cmd;
gcp_cmd_msg_t* cmdtrx;
gcp_cmd_msg_t* cmdctx;
if ( !m || !t || !c ) return NULL;
if (persistent) {
if (m->committed) {
DISSECTOR_ASSERT(t->cmds != NULL);
for (cmdctx = t->cmds; cmdctx; cmdctx = cmdctx->next) {
cmd = cmdctx->cmd;
if (cmd->msg == m && cmd->offset == offset) {
return cmd;
}
}
DISSECTOR_ASSERT(!"called for a command that does not exist!");
return NULL;
} else {
cmd = wmem_new(wmem_file_scope(), gcp_cmd_t);
cmdtrx = wmem_new(wmem_file_scope(), gcp_cmd_msg_t);
cmdctx = wmem_new(wmem_file_scope(), gcp_cmd_msg_t);
}
} else {
cmd = wmem_new(wmem_packet_scope(), gcp_cmd_t);
cmdtrx = wmem_new(wmem_packet_scope(), gcp_cmd_msg_t);
cmdctx = wmem_new(wmem_packet_scope(), gcp_cmd_msg_t);
}
cmd->type = type;
cmd->offset = offset;
cmd->terms.term = NULL;
cmd->terms.next = NULL;
cmd->terms.last = &(cmd->terms);
cmd->str = NULL;
cmd->msg = m;
if ((type != GCP_CMD_NONE) && (!persistent)){
cmd->str = val_to_str_const(type, gcp_cmd_type, "Unknown");
}
cmd->trx = t;
cmd->ctx = c;
cmd->error = 0;
cmdctx->cmd = cmdtrx->cmd = cmd;
cmdctx->next = cmdtrx->next = NULL;
cmdctx->last = cmdtrx->last = NULL;
if (t->cmds) {
t->cmds->last->next = cmdtrx;
t->cmds->last = cmdtrx;
} else {
t->cmds = cmdtrx;
t->cmds->last = cmdtrx;
}
if (c->cmds) {
c->cmds->last->next = cmdctx;
c->cmds->last = cmdctx;
} else {
c->cmds = cmdctx;
c->cmds->last = cmdctx;
}
return cmd;
}
gcp_term_t* gcp_cmd_add_term(gcp_msg_t* m, gcp_trx_t* tr, gcp_cmd_t* c, gcp_term_t* t, gcp_wildcard_t wildcard, gboolean persistent) {
gcp_terms_t* ct;
gcp_terms_t* ct2;
static gcp_term_t all_terms = {"$",(const guint8*)"",1,GCP_TERM_TYPE_UNKNOWN,NULL,NULL,NULL};
if ( !c ) return NULL;
if ( wildcard == GCP_WILDCARD_CHOOSE) {
return &all_terms;
}
if (persistent) {
if ( c->msg->committed ) {
if (wildcard == GCP_WILDCARD_ALL) {
for (ct = c->ctx->terms.next; ct; ct = ct->next) {
/* XXX not handling more wilcards in one msg */
if ( ct->term->start == m ) {
return ct->term;
}
}
return NULL;
} else {
for (ct = c->ctx->terms.next; ct; ct = ct->next) {
if ( g_str_equal(ct->term->str,t->str) ) {
return ct->term;
}
}
return NULL;
}
} else {
for (ct = c->ctx->terms.next; ct; ct = ct->next) {
if ( g_str_equal(ct->term->str,t->str) || ct->term->start == m) {
break;
}
}
if ( ! ct ) {
if (wildcard == GCP_WILDCARD_ALL) {
ct = wmem_new(wmem_file_scope(), gcp_terms_t);
ct->next = NULL;
ct->term = wmem_new0(wmem_file_scope(), gcp_term_t);
ct->term->start = m;
ct->term->str = "*";
ct->term->buffer = NULL;
ct->term->len = 0;
c->terms.last = c->terms.last->next = ct;
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->ctx->terms.last->next = ct2;
c->ctx->terms.last = ct2;
return ct->term;
} else {
for (ct = c->ctx->terms.next; ct; ct = ct->next) {
/* XXX not handling more wilcards in one msg */
if ( ct->term->buffer == NULL && tr->cmds->cmd->msg == ct->term->start ) {
ct->term->str = wmem_strdup(wmem_file_scope(), t->str);
ct->term->buffer = (const guint8 *)wmem_memdup(wmem_file_scope(), t->buffer,t->len);
ct->term->len = t->len;
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->terms.last = c->terms.last->next = ct2;
return ct->term;
}
if ( g_str_equal(ct->term->str,t->str) ) {
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->terms.last = c->terms.last->next = ct2;
return ct->term;
}
}
ct = wmem_new(wmem_file_scope(), gcp_terms_t);
ct->next = NULL;
ct->term = wmem_new0(wmem_file_scope(), gcp_term_t);
ct->term->start = m;
ct->term->str = wmem_strdup(wmem_file_scope(), t->str);
ct->term->buffer = (const guint8 *)wmem_memdup(wmem_file_scope(), t->buffer,t->len);
ct->term->len = t->len;
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->terms.last = c->terms.last->next = ct2;
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->ctx->terms.last = c->ctx->terms.last->next = ct2;
return ct->term;
}
} else {
ct2 = wmem_new0(wmem_file_scope(), gcp_terms_t);
ct2->term = ct->term;
c->terms.last = c->terms.last->next = ct2;
return ct->term;
}
DISSECTOR_ASSERT_NOT_REACHED();
}
} else {
ct = wmem_new(wmem_packet_scope(), gcp_terms_t);
ct->term = t;
ct->next = NULL;
c->terms.last = c->terms.last->next = ct;
return t;
}
}
const gchar* gcp_cmd_to_str(gcp_cmd_t* c, gboolean persistent) {
const gchar* s;
gcp_terms_t* term;
if ( !c ) return "-";
switch (c->type) {
case GCP_CMD_NONE:
return "-";
break;
case GCP_CMD_ADD_REQ:
s = "AddReq {";
break;
case GCP_CMD_MOVE_REQ:
s = "MoveReq {";
break;
case GCP_CMD_MOD_REQ:
s = "ModReq {";
break;
case GCP_CMD_SUB_REQ:
s = "SubReq {";
break;
case GCP_CMD_AUDITCAP_REQ:
s = "AuditCapReq {";
break;
case GCP_CMD_AUDITVAL_REQ:
s = "AuditValReq {";
break;
case GCP_CMD_NOTIFY_REQ:
s = "NotifyReq {";
break;
case GCP_CMD_SVCCHG_REQ:
s = "SvcChgReq {";
break;
case GCP_CMD_TOPOLOGY_REQ:
s = "TopologyReq {";
break;
case GCP_CMD_CTX_ATTR_AUDIT_REQ:
s = "CtxAttribAuditReq {";
break;
case GCP_CMD_ADD_REPLY:
s = "AddReply {";
break;
case GCP_CMD_MOVE_REPLY:
s = "MoveReply {";
break;
case GCP_CMD_MOD_REPLY:
s = "ModReply {";
break;
case GCP_CMD_SUB_REPLY:
s = "SubReply {";
break;
case GCP_CMD_AUDITCAP_REPLY:
s = "AuditCapReply {";
break;
case GCP_CMD_AUDITVAL_REPLY:
s = "AuditValReply {";
break;
case GCP_CMD_NOTIFY_REPLY:
s = "NotifyReply {";
break;
case GCP_CMD_SVCCHG_REPLY:
s = "SvcChgReply {";
break;
case GCP_CMD_TOPOLOGY_REPLY:
s = "TopologyReply {";
break;
case GCP_CMD_REPLY:
s = "ActionReply {";
break;
case GCP_CMD_OTHER_REQ:
s = "Request {";
break;
default:
s = "-";
break;
}
for (term = c->terms.next; term; term = term->next) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,term->term->str);
}
if (c->error) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s Error=%i",s,c->error);
}
s = wmem_strdup_printf(wmem_packet_scope(), "%s }", s);
if (persistent) {
if (! c->str) c->str = wmem_strdup(wmem_file_scope(), s);
} else {
c->str = s;
}
return s;
}
static const gchar* gcp_trx_to_str(gcp_msg_t* m, gcp_trx_t* t, gboolean persistent) {
gchar* s;
gcp_cmd_msg_t* c;
if ( !m || !t ) return "-";
s = wmem_strdup_printf(wmem_packet_scope(), "T %x { ",t->id);
if (t->cmds) {
if (t->cmds->cmd->ctx) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s C %x {",s,t->cmds->cmd->ctx->id);
for (c = t->cmds; c; c = c->next) {
if (c->cmd->msg == m) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,gcp_cmd_to_str(c->cmd,persistent));
}
}
s = wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,"}");
}
}
if (t->error) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s Error=%i",s,t->error);
}
return wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,"}");
}
const gchar* gcp_msg_to_str(gcp_msg_t* m, gboolean persistent) {
gcp_trx_msg_t* t;
const gchar* s = "";
if ( !m ) return "-";
for (t = m->trxs; t; t = t->next) {
s = wmem_strdup_printf(wmem_packet_scope(), "%s %s",s,gcp_trx_to_str(m,t->trx, persistent));
}
return s;
}
typedef struct _gcp_ctxs_t {
struct _gcp_ctx_t* ctx;
struct _gcp_ctxs_t* next;
} gcp_ctxs_t;
/*static const gchar* trx_types[] = {"None","Req","Reply","Pending","Ack"};*/
void gcp_analyze_msg(proto_tree* gcp_tree, packet_info* pinfo, tvbuff_t* gcp_tvb, gcp_msg_t* m, gcp_hf_ett_t* ids, expert_field* command_err) {
gcp_trx_msg_t* t;
gcp_ctxs_t contexts = {NULL,NULL};
gcp_ctxs_t* ctx_node;
gcp_cmd_msg_t* c;
for (t = m->trxs; t; t = t->next) {
for (c = t->trx->cmds; c; c = c->next) {
gcp_ctx_t* ctx = c->cmd->ctx;
for (ctx_node = contexts.next; ctx_node; ctx_node = ctx_node->next) {
if (ctx_node->ctx->id == ctx->id) {
break;
}
}
if (! ctx_node) {
ctx_node = wmem_new(wmem_packet_scope(), gcp_ctxs_t);
ctx_node->ctx = ctx;
ctx_node->next = contexts.next;
contexts.next = ctx_node;
}
}
}
for (ctx_node = contexts.next; ctx_node; ctx_node = ctx_node->next) {
gcp_ctx_t* ctx = ctx_node->ctx;
proto_item* ctx_item = proto_tree_add_uint(gcp_tree,ids->hf.ctx,gcp_tvb,0,0,ctx->id);
proto_tree* ctx_tree = proto_item_add_subtree(ctx_item,ids->ett.ctx);
gcp_terms_t *ctx_term;
PROTO_ITEM_SET_GENERATED(ctx_item);
if (ctx->cmds) {
proto_tree* history_tree = proto_tree_add_subtree(ctx_tree,gcp_tvb,0,0,ids->ett.ctx_cmds,NULL,"[ Command History ]");
for (c = ctx->cmds; c; c = c->next) {
proto_item* cmd_item = proto_tree_add_uint(history_tree,ids->hf.ctx_cmd,gcp_tvb,0,0,c->cmd->msg->framenum);
if (c->cmd->str) proto_item_append_text(cmd_item," %s ",c->cmd->str);
PROTO_ITEM_SET_GENERATED(cmd_item);
if (c->cmd->error) {
expert_add_info(pinfo, cmd_item, command_err);
}
}
}
if (( ctx_term = ctx->terms.next )) {
proto_tree* terms_tree = proto_tree_add_subtree(ctx_tree,gcp_tvb,0,0,ids->ett.ctx_terms,NULL,"[ Terminations Used ]");
for (; ctx_term; ctx_term = ctx_term->next ) {
if ( ctx_term->term && ctx_term->term->str) {
proto_item* pi = proto_tree_add_string(terms_tree,ids->hf.ctx_term,gcp_tvb,0,0,ctx_term->term->str);
proto_tree* term_tree = proto_item_add_subtree(pi,ids->ett.ctx_term);
PROTO_ITEM_SET_GENERATED(pi);
if (ctx_term->term->type) {
pi = proto_tree_add_uint(term_tree,ids->hf.ctx_term_type,gcp_tvb,0,0,ctx_term->term->type);
PROTO_ITEM_SET_GENERATED(pi);
}
if (ctx_term->term->bir) {
pi = proto_tree_add_string(term_tree,ids->hf.ctx_term_bir,gcp_tvb,0,0,ctx_term->term->bir);
PROTO_ITEM_SET_GENERATED(pi);
}
if (ctx_term->term->nsap) {
pi = proto_tree_add_string(term_tree,ids->hf.ctx_term_nsap,gcp_tvb,0,0,ctx_term->term->nsap);
PROTO_ITEM_SET_GENERATED(pi);
}
if (ctx_term->term->bir && ctx_term->term->nsap) {
gchar* tmp_key = wmem_strdup_printf(wmem_packet_scope(), "%s:%s",ctx_term->term->nsap,ctx_term->term->bir);
gchar* key = g_ascii_strdown(tmp_key, -1);
alcap_tree_from_bearer_key(term_tree, gcp_tvb, pinfo, key);
g_free(key);
}
}
}
}
}
}
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

View File

@ -1,224 +0,0 @@
/* gcp.h
* Gateway Control Protocol -- Context Tracking
*
* 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
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#ifndef __GCP_H_
#define __GCP_H_
#include <glib.h>
#include <epan/packet.h>
#include <epan/conversation.h>
#include <epan/strutil.h>
#include <epan/wmem/wmem.h>
#include <epan/expert.h>
#include <epan/prefs.h>
#include <epan/asn1.h>
#include <epan/dissectors/packet-ber.h>
#include <epan/dissectors/packet-q931.h>
#include <epan/dissectors/packet-mtp3.h>
#include <epan/dissectors/packet-alcap.h>
#include <epan/dissectors/packet-isup.h>
#include <epan/sctpppids.h>
#include "ws_symbol_export.h"
typedef struct _gcp_hf_ett_t {
struct {
int ctx;
int ctx_cmd;
int ctx_term;
int ctx_term_type;
int ctx_term_bir;
int ctx_term_nsap;
} hf;
struct {
gint ctx;
gint ctx_cmds;
gint ctx_terms;
gint ctx_term;
} ett;
} gcp_hf_ett_t;
#define NULL_CONTEXT 0
#define CHOOSE_CONTEXT 0xFFFFFFFE
#define ALL_CONTEXTS 0xFFFFFFFF
typedef enum {
GCP_CMD_NONE,
GCP_CMD_ADD_REQ,
GCP_CMD_MOVE_REQ,
GCP_CMD_MOD_REQ,
GCP_CMD_SUB_REQ,
GCP_CMD_AUDITCAP_REQ,
GCP_CMD_AUDITVAL_REQ,
GCP_CMD_NOTIFY_REQ,
GCP_CMD_SVCCHG_REQ,
GCP_CMD_TOPOLOGY_REQ,
GCP_CMD_CTX_ATTR_AUDIT_REQ,
GCP_CMD_OTHER_REQ,
GCP_CMD_ADD_REPLY,
GCP_CMD_MOVE_REPLY,
GCP_CMD_MOD_REPLY,
GCP_CMD_SUB_REPLY,
GCP_CMD_AUDITCAP_REPLY,
GCP_CMD_AUDITVAL_REPLY,
GCP_CMD_NOTIFY_REPLY,
GCP_CMD_SVCCHG_REPLY,
GCP_CMD_TOPOLOGY_REPLY,
GCP_CMD_REPLY
} gcp_cmd_type_t;
typedef enum {
GCP_TRX_NONE,
GCP_TRX_REQUEST,
GCP_TRX_PENDING,
GCP_TRX_REPLY,
GCP_TRX_ACK
} gcp_trx_type_t;
typedef struct _gcp_msg_t {
guint32 lo_addr;
guint32 hi_addr;
guint32 framenum;
nstime_t time;
struct _gcp_trx_msg_t* trxs;
gboolean committed;
} gcp_msg_t;
typedef struct _gcp_trx_msg_t {
struct _gcp_trx_t* trx;
struct _gcp_trx_msg_t* next;
struct _gcp_trx_msg_t* last;
} gcp_trx_msg_t;
typedef struct _gcp_cmd_msg_t {
struct _gcp_cmd_t* cmd;
struct _gcp_cmd_msg_t* next;
struct _gcp_cmd_msg_t* last;
} gcp_cmd_msg_t;
typedef struct _gcp_trx_t {
gcp_msg_t* initial;
guint32 id;
gcp_trx_type_t type;
guint pendings;
struct _gcp_cmd_msg_t* cmds;
struct _gcp_trx_ctx_t* ctxs;
guint error;
} gcp_trx_t;
#define GCP_TERM_TYPE_UNKNOWN 0
#define GCP_TERM_TYPE_AAL1 1
#define GCP_TERM_TYPE_AAL2 2
#define GCP_TERM_TYPE_AAL1_STRUCT 3
#define GCP_TERM_TYPE_IP_RTP 4
#define GCP_TERM_TYPE_TDM 5
typedef enum _gcp_wildcard_t {
GCP_WILDCARD_NONE,
GCP_WILDCARD_CHOOSE,
GCP_WILDCARD_ALL
} gcp_wildcard_t;
typedef struct _gcp_term_t {
const gchar* str;
const guint8* buffer;
guint len;
guint type;
gchar* bir;
gchar* nsap;
gcp_msg_t* start;
} gcp_term_t;
typedef struct _gcp_terms_t {
gcp_term_t* term;
struct _gcp_terms_t* next;
struct _gcp_terms_t* last;
} gcp_terms_t;
typedef struct _gcp_cmd_t {
guint offset;
const gchar* str;
gcp_cmd_type_t type;
gcp_terms_t terms;
struct _gcp_msg_t* msg;
struct _gcp_trx_t* trx;
struct _gcp_ctx_t* ctx;
guint error;
} gcp_cmd_t;
typedef struct _gcp_ctx_t {
gcp_msg_t* initial;
guint32 id;
struct _gcp_cmd_msg_t* cmds;
struct _gcp_ctx_t* prev;
gcp_terms_t terms;
} gcp_ctx_t;
WS_DLL_PUBLIC const value_string gcp_cmd_type[];
WS_DLL_PUBLIC const value_string gcp_term_types[];
extern void gcp_init(void);
extern gcp_msg_t* gcp_msg(packet_info* pinfo, int o, gboolean persistent);
extern gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean persistent);
extern gcp_ctx_t* gcp_ctx(gcp_msg_t* m, gcp_trx_t* t, guint32 c_id, gboolean persistent);
extern gcp_cmd_t* gcp_cmd(gcp_msg_t* m, gcp_trx_t* t, gcp_ctx_t* c, gcp_cmd_type_t type, guint offset, gboolean persistent);
extern gcp_term_t* gcp_cmd_add_term(gcp_msg_t* m, gcp_trx_t* tr, gcp_cmd_t* c, gcp_term_t* t, gcp_wildcard_t wildcard, gboolean persistent);
extern void gcp_analyze_msg(proto_tree* gcp_tree, packet_info* pinfo, tvbuff_t* gcp_tvb, gcp_msg_t* m, gcp_hf_ett_t* ids, expert_field* command_err);
extern const gchar* gcp_cmd_to_str(gcp_cmd_t* c, gboolean persistent);
extern const gchar* gcp_msg_to_str(gcp_msg_t* m, gboolean persistent);
#define gcp_cmd_set_error(c,e) (c->error = e)
#define gcp_trx_set_error(t,e) (t->error = e)
#define GCP_ETT_ARR_ELEMS(gi) &(gi.ett.ctx),&(gi.ett.ctx_cmds),&(gi.ett.ctx_terms),&(gi.ett.ctx_term)
#define GCP_HF_ARR_ELEMS(n,gi) \
{ &(gi.hf.ctx), { "Context", n ".ctx", FT_UINT32, BASE_HEX, NULL, 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_term), { "Termination", n ".ctx.term", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_term_type), { "Type", n ".ctx.term.type", FT_UINT32, BASE_HEX, VALS(gcp_term_types), 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_term_bir), { "BIR", n ".ctx.term.bir", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_term_nsap), { "NSAP", n ".ctx.term.nsap", FT_STRING, BASE_NONE, NULL, 0, NULL, HFILL }}, \
{ &(gi.hf.ctx_cmd), { "Command in Frame", n ".ctx.cmd", FT_FRAMENUM, BASE_NONE, NULL, 0, NULL, HFILL }}
#endif
/*
* Editor modelines - http://www.wireshark.org/tools/modelines.html
*
* Local variables:
* c-basic-offset: 4
* tab-width: 8
* indent-tabs-mode: nil
* End:
*
* vi: set shiftwidth=4 tabstop=8 expandtab:
* :indentSize=4:tabSize=8:noTabs=true:
*/

View File

@ -39,12 +39,16 @@
#include "epan/epan_dissect.h"
#include "epan/packet.h"
#include "epan/proto_data.h"
#include "epan/to_str.h"
#include "epan/dissectors/packet-sip.h"
#include "epan/dissectors/packet-h225.h"
#include "epan/dissectors/packet-h245.h"
#include "epan/dissectors/packet-isup.h"
#include "epan/dissectors/packet-sdp.h"
#include "epan/dissectors/packet-mgcp.h"
#include "epan/dissectors/packet-mtp3.h"
#include "epan/dissectors/packet-actrace.h"
#include "epan/dissectors/packet-q931.h"
#include "epan/dissectors/packet-rtp.h"
#include "epan/dissectors/packet-rtp-events.h"
#include "epan/dissectors/packet-t38.h"