Handle hop-by-hop-id collisions (when matching requests and answers) better:
instead of storing the requests in an se_tree (keyed by hop-by-hop-id), store an se_tree which is itself keyed by frame number. When looking for a matching request, first find the tree of pdus (by hop-by-hop-id) and then look for the largest frame number less than or equal to the answer's frame number. Also verify that the end-to-end-id matches. Move the conversation structure out of packet-diameter.h: it's only used in packet-diameter.c svn path=/trunk/; revision=46553
This commit is contained in:
parent
b369116122
commit
01fd357171
|
@ -96,52 +96,57 @@
|
|||
#define DIAMETER_V16 16
|
||||
#define DIAMETER_RFC 1
|
||||
|
||||
/* Conversation Info */
|
||||
typedef struct _diameter_conv_info_t {
|
||||
emem_tree_t *pdus_tree;
|
||||
} diameter_conv_info_t;
|
||||
|
||||
typedef struct _diam_ctx_t {
|
||||
proto_tree* tree;
|
||||
packet_info* pinfo;
|
||||
emem_tree_t* avps;
|
||||
proto_tree *tree;
|
||||
packet_info *pinfo;
|
||||
emem_tree_t *avps;
|
||||
gboolean version_rfc;
|
||||
} diam_ctx_t;
|
||||
|
||||
typedef struct _diam_avp_t diam_avp_t;
|
||||
typedef struct _avp_type_t avp_type_t;
|
||||
|
||||
typedef const char* (*diam_avp_dissector_t)(diam_ctx_t*, diam_avp_t*, tvbuff_t*);
|
||||
typedef const char *(*diam_avp_dissector_t)(diam_ctx_t *, diam_avp_t *, tvbuff_t *);
|
||||
|
||||
|
||||
typedef struct _diam_vnd_t {
|
||||
guint32 code;
|
||||
GArray* vs_avps;
|
||||
value_string_ext* vs_avps_ext;
|
||||
GArray* vs_cmds;
|
||||
GArray *vs_avps;
|
||||
value_string_ext *vs_avps_ext;
|
||||
GArray *vs_cmds;
|
||||
} diam_vnd_t;
|
||||
|
||||
struct _diam_avp_t {
|
||||
guint32 code;
|
||||
const diam_vnd_t* vendor;
|
||||
const diam_vnd_t *vendor;
|
||||
diam_avp_dissector_t dissector_v16;
|
||||
diam_avp_dissector_t dissector_rfc;
|
||||
|
||||
gint ett;
|
||||
int hf_value;
|
||||
void* type_data;
|
||||
void *type_data;
|
||||
};
|
||||
|
||||
#define VND_AVP_VS(v) ((value_string*)(void*)((v)->vs_avps->data))
|
||||
#define VND_AVP_VS(v) ((value_string *)(void *)((v)->vs_avps->data))
|
||||
#define VND_AVP_VS_LEN(v) ((v)->vs_avps->len)
|
||||
#define VND_CMD_VS(v) ((value_string*)(void*)((v)->vs_cmds->data))
|
||||
#define VND_CMD_VS(v) ((value_string *)(void *)((v)->vs_cmds->data))
|
||||
|
||||
typedef struct _diam_dictionary_t {
|
||||
emem_tree_t* avps;
|
||||
emem_tree_t* vnds;
|
||||
value_string* applications;
|
||||
value_string* commands;
|
||||
emem_tree_t *avps;
|
||||
emem_tree_t *vnds;
|
||||
value_string *applications;
|
||||
value_string *commands;
|
||||
} diam_dictionary_t;
|
||||
|
||||
typedef diam_avp_t* (*avp_constructor_t)(const avp_type_t*, guint32, const diam_vnd_t*, const char*, const value_string*, void*);
|
||||
typedef diam_avp_t *(*avp_constructor_t)(const avp_type_t *, guint32, const diam_vnd_t *, const char *, const value_string *, void *);
|
||||
|
||||
struct _avp_type_t {
|
||||
const char* name;
|
||||
const char *name;
|
||||
diam_avp_dissector_t v16;
|
||||
diam_avp_dissector_t rfc;
|
||||
enum ftenum ft;
|
||||
|
@ -150,10 +155,10 @@ struct _avp_type_t {
|
|||
};
|
||||
|
||||
struct _build_dict {
|
||||
GArray* hf;
|
||||
GPtrArray* ett;
|
||||
GHashTable* types;
|
||||
GHashTable* avps;
|
||||
GArray *hf;
|
||||
GPtrArray *ett;
|
||||
GHashTable *types;
|
||||
GHashTable *avps;
|
||||
};
|
||||
|
||||
|
||||
|
@ -172,20 +177,20 @@ typedef enum {
|
|||
} avp_reassemble_mode_t;
|
||||
|
||||
typedef struct _proto_avp_t {
|
||||
char* name;
|
||||
char *name;
|
||||
dissector_handle_t handle;
|
||||
avp_reassemble_mode_t reassemble_mode;
|
||||
} proto_avp_t;
|
||||
|
||||
static const char* simple_avp(diam_ctx_t*, diam_avp_t*, tvbuff_t*);
|
||||
static const char *simple_avp(diam_ctx_t *, diam_avp_t *, tvbuff_t *);
|
||||
|
||||
static diam_vnd_t unknown_vendor = { 0xffffffff, NULL, NULL, NULL };
|
||||
static diam_vnd_t no_vnd = { 0, NULL, NULL, NULL };
|
||||
static diam_avp_t unknown_avp = {0, &unknown_vendor, simple_avp, simple_avp, -1, -1, NULL };
|
||||
static GArray* all_cmds;
|
||||
static GArray *all_cmds;
|
||||
static diam_dictionary_t dictionary = { NULL, NULL, NULL, NULL };
|
||||
static struct _build_dict build_dict;
|
||||
static const value_string* vnd_short_vs;
|
||||
static const value_string *vnd_short_vs;
|
||||
static dissector_handle_t data_handle;
|
||||
static dissector_handle_t eap_handle;
|
||||
|
||||
|
@ -289,7 +294,7 @@ static dissector_table_t diameter_dissector_table;
|
|||
static dissector_table_t diameter_3gpp_avp_dissector_table;
|
||||
static dissector_table_t diameter_ericsson_avp_dissector_table;
|
||||
|
||||
static const char* avpflags_str[] = {
|
||||
static const char *avpflags_str[] = {
|
||||
"---",
|
||||
"--P",
|
||||
"-M-",
|
||||
|
@ -303,8 +308,8 @@ static const char* avpflags_str[] = {
|
|||
static gint
|
||||
compare_avps (gconstpointer a, gconstpointer b)
|
||||
{
|
||||
value_string* vsa = (value_string*)a;
|
||||
value_string* vsb = (value_string*)b;
|
||||
value_string *vsa = (value_string *)a;
|
||||
value_string *vsb = (value_string *)b;
|
||||
|
||||
if(vsa->value > vsb->value)
|
||||
return 1;
|
||||
|
@ -367,7 +372,7 @@ dissect_diameter_base_framed_ipv6_prefix(tvbuff_t *tvb, packet_info *pinfo _U_,
|
|||
|
||||
/* Dissect an AVP at offset */
|
||||
static int
|
||||
dissect_diameter_avp(diam_ctx_t* c, tvbuff_t* tvb, int offset)
|
||||
dissect_diameter_avp(diam_ctx_t *c, tvbuff_t *tvb, int offset)
|
||||
{
|
||||
guint32 code = tvb_get_ntohl(tvb,offset);
|
||||
guint32 len = tvb_get_ntohl(tvb,offset+4);
|
||||
|
@ -380,20 +385,20 @@ dissect_diameter_avp(diam_ctx_t* c, tvbuff_t* tvb, int offset)
|
|||
{1,&vendorid},
|
||||
{0,NULL}
|
||||
};
|
||||
diam_avp_t* a = (diam_avp_t*)emem_tree_lookup32_array(dictionary.avps,k);
|
||||
diam_avp_t *a = (diam_avp_t *)emem_tree_lookup32_array(dictionary.avps,k);
|
||||
proto_item *pi, *avp_item;
|
||||
proto_tree *avp_tree, *save_tree;
|
||||
tvbuff_t* subtvb;
|
||||
diam_vnd_t* vendor;
|
||||
const char* code_str;
|
||||
const char* avp_str;
|
||||
tvbuff_t *subtvb;
|
||||
diam_vnd_t *vendor;
|
||||
const char *code_str;
|
||||
const char *avp_str;
|
||||
len &= 0x00ffffff;
|
||||
|
||||
if (!a) {
|
||||
a = &unknown_avp;
|
||||
|
||||
if (vendor_flag) {
|
||||
if (! (vendor = (diam_vnd_t*)emem_tree_lookup32(dictionary.vnds,vendorid) ))
|
||||
if (! (vendor = (diam_vnd_t *)emem_tree_lookup32(dictionary.vnds,vendorid) ))
|
||||
vendor = &unknown_vendor;
|
||||
} else {
|
||||
vendor = &no_vnd;
|
||||
|
@ -408,7 +413,7 @@ dissect_diameter_avp(diam_ctx_t* c, tvbuff_t* tvb, int offset)
|
|||
g_strdup_printf("diameter_vendor_%s",val_to_str_ext_const(vendorid, &sminmpec_values_ext, "Unknown")));
|
||||
#if 0
|
||||
{ /* Debug code */
|
||||
value_string* vendor_avp_vs=VALUE_STRING_EXT_VS_P(vendor->vs_avps_ext);
|
||||
value_string *vendor_avp_vs=VALUE_STRING_EXT_VS_P(vendor->vs_avps_ext);
|
||||
gint i = 0;
|
||||
while(vendor_avp_vs[i].strptr!=NULL) {
|
||||
g_warning("%u %s",vendor_avp_vs[i].value,vendor_avp_vs[i].strptr);
|
||||
|
@ -428,8 +433,8 @@ dissect_diameter_avp(diam_ctx_t* c, tvbuff_t* tvb, int offset)
|
|||
|
||||
/* Code */
|
||||
if (a == &unknown_avp) {
|
||||
proto_tree* tu = proto_item_add_subtree(pi,ett_unknown);
|
||||
proto_item* iu = proto_tree_add_text(tu,tvb,offset,4,"Unknown AVP, "
|
||||
proto_tree *tu = proto_item_add_subtree(pi,ett_unknown);
|
||||
proto_item *iu = proto_tree_add_text(tu,tvb,offset,4,"Unknown AVP, "
|
||||
"if you know what this is you can add it to dictionary.xml");
|
||||
expert_add_info_format(c->pinfo, iu, PI_UNDECODED, PI_WARN,
|
||||
"Unknown AVP %u (vendor=%s)", code,
|
||||
|
@ -444,7 +449,7 @@ dissect_diameter_avp(diam_ctx_t* c, tvbuff_t* tvb, int offset)
|
|||
/* Flags */
|
||||
pi = proto_tree_add_item(avp_tree,hf_diameter_avp_flags,tvb,offset,1,ENC_BIG_ENDIAN);
|
||||
{
|
||||
proto_tree* flags_tree = proto_item_add_subtree(pi,ett_diameter_avp_flags);
|
||||
proto_tree *flags_tree = proto_item_add_subtree(pi,ett_diameter_avp_flags);
|
||||
proto_tree_add_item(flags_tree,hf_diameter_avp_flags_vendor_specific,tvb,offset,1,ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(flags_tree,hf_diameter_avp_flags_mandatory,tvb,offset,1,ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(flags_tree,hf_diameter_avp_flags_protected,tvb,offset,1,ENC_BIG_ENDIAN);
|
||||
|
@ -470,8 +475,8 @@ dissect_diameter_avp(diam_ctx_t* c, tvbuff_t* tvb, int offset)
|
|||
proto_item_append_text(avp_item," vnd=%s", val_to_str(vendorid, vnd_short_vs, "%d"));
|
||||
pi = proto_tree_add_item(avp_tree,hf_diameter_avp_vendor_id,tvb,offset,4,ENC_BIG_ENDIAN);
|
||||
if (vendor == &unknown_vendor) {
|
||||
proto_tree* tu = proto_item_add_subtree(pi,ett_unknown);
|
||||
proto_item* iu = proto_tree_add_text(tu,tvb,offset,4,"Unknown Vendor, "
|
||||
proto_tree *tu = proto_item_add_subtree(pi,ett_unknown);
|
||||
proto_item *iu = proto_tree_add_text(tu,tvb,offset,4,"Unknown Vendor, "
|
||||
"if you know whose this is you can add it to dictionary.xml");
|
||||
expert_add_info_format(c->pinfo, iu, PI_UNDECODED, PI_WARN, "Unknown Vendor");
|
||||
PROTO_ITEM_SET_GENERATED(iu);
|
||||
|
@ -481,7 +486,7 @@ dissect_diameter_avp(diam_ctx_t* c, tvbuff_t* tvb, int offset)
|
|||
|
||||
if ( len == (guint32)(vendor_flag ? 12 : 8) ) {
|
||||
/* Data is empty so return now */
|
||||
proto_item* iu = proto_tree_add_text(avp_tree,tvb,offset,0,"No data");
|
||||
proto_item *iu = proto_tree_add_text(avp_tree,tvb,offset,0,"No data");
|
||||
expert_add_info_format(c->pinfo, iu, PI_UNDECODED, PI_WARN, "Data is empty");
|
||||
PROTO_ITEM_SET_GENERATED(iu);
|
||||
return len;
|
||||
|
@ -521,13 +526,13 @@ dissect_diameter_avp(diam_ctx_t* c, tvbuff_t* tvb, int offset)
|
|||
return len;
|
||||
}
|
||||
|
||||
static const char*
|
||||
address_rfc_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
address_rfc_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
char* label = (char*)ep_alloc(ITEM_LABEL_LENGTH+1);
|
||||
address_avp_t* t = a->type_data;
|
||||
proto_item* pi = proto_tree_add_item(c->tree,a->hf_value,tvb,0,tvb_length(tvb),ENC_BIG_ENDIAN);
|
||||
proto_tree* pt = proto_item_add_subtree(pi,t->ett);
|
||||
char *label = (char *)ep_alloc(ITEM_LABEL_LENGTH+1);
|
||||
address_avp_t *t = a->type_data;
|
||||
proto_item *pi = proto_tree_add_item(c->tree,a->hf_value,tvb,0,tvb_length(tvb),ENC_BIG_ENDIAN);
|
||||
proto_tree *pt = proto_item_add_subtree(pi,t->ett);
|
||||
guint32 addr_type = tvb_get_ntohs(tvb,0);
|
||||
gint len = tvb_length_remaining(tvb,2);
|
||||
|
||||
|
@ -559,10 +564,10 @@ address_rfc_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
|||
return label;
|
||||
}
|
||||
|
||||
static const char*
|
||||
proto_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
proto_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
proto_avp_t* t = a->type_data;
|
||||
proto_avp_t *t = a->type_data;
|
||||
|
||||
col_set_writable(c->pinfo->cinfo, FALSE);
|
||||
|
||||
|
@ -576,12 +581,12 @@ proto_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
|||
return "";
|
||||
}
|
||||
|
||||
static const char*
|
||||
time_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
time_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
int len = tvb_length(tvb);
|
||||
char* label = ep_alloc(ITEM_LABEL_LENGTH+1);
|
||||
proto_item* pi;
|
||||
char *label = ep_alloc(ITEM_LABEL_LENGTH+1);
|
||||
proto_item *pi;
|
||||
|
||||
if ( len != 4 ) {
|
||||
pi = proto_tree_add_text(c->tree, tvb, 0, 4, "Error! AVP value MUST be 4 bytes");
|
||||
|
@ -596,13 +601,13 @@ time_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
|||
return label;
|
||||
}
|
||||
|
||||
static const char*
|
||||
address_v16_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
address_v16_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
char* label = ep_alloc(ITEM_LABEL_LENGTH+1);
|
||||
address_avp_t* t = a->type_data;
|
||||
proto_item* pi = proto_tree_add_item(c->tree,a->hf_value,tvb,0,tvb_length(tvb),ENC_BIG_ENDIAN);
|
||||
proto_tree* pt = proto_item_add_subtree(pi,t->ett);
|
||||
char *label = ep_alloc(ITEM_LABEL_LENGTH+1);
|
||||
address_avp_t *t = a->type_data;
|
||||
proto_item *pi = proto_tree_add_item(c->tree,a->hf_value,tvb,0,tvb_length(tvb),ENC_BIG_ENDIAN);
|
||||
proto_tree *pt = proto_item_add_subtree(pi,t->ett);
|
||||
guint32 len = tvb_length(tvb);
|
||||
|
||||
switch (len) {
|
||||
|
@ -625,31 +630,31 @@ address_v16_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
|||
return label;
|
||||
}
|
||||
|
||||
static const char*
|
||||
simple_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
simple_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
char* label = ep_alloc(ITEM_LABEL_LENGTH+1);
|
||||
proto_item* pi = proto_tree_add_item(c->tree,a->hf_value,tvb,0,tvb_length(tvb),ENC_BIG_ENDIAN);
|
||||
char *label = ep_alloc(ITEM_LABEL_LENGTH+1);
|
||||
proto_item *pi = proto_tree_add_item(c->tree,a->hf_value,tvb,0,tvb_length(tvb),ENC_BIG_ENDIAN);
|
||||
proto_item_fill_label(PITEM_FINFO(pi), label);
|
||||
label = strstr(label,": ")+2;
|
||||
return label;
|
||||
}
|
||||
|
||||
static const char*
|
||||
utf8_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
utf8_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
char* label = ep_alloc(ITEM_LABEL_LENGTH+1);
|
||||
proto_item* pi = proto_tree_add_item(c->tree,a->hf_value,tvb,0,tvb_length(tvb),ENC_UTF_8|ENC_BIG_ENDIAN);
|
||||
char *label = ep_alloc(ITEM_LABEL_LENGTH+1);
|
||||
proto_item *pi = proto_tree_add_item(c->tree,a->hf_value,tvb,0,tvb_length(tvb),ENC_UTF_8|ENC_BIG_ENDIAN);
|
||||
proto_item_fill_label(PITEM_FINFO(pi), label);
|
||||
label = strstr(label,": ")+2;
|
||||
return label;
|
||||
}
|
||||
|
||||
static const char*
|
||||
integer32_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
integer32_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
char* label;
|
||||
proto_item* pi;
|
||||
char *label;
|
||||
proto_item *pi;
|
||||
|
||||
/* Verify length before adding */
|
||||
gint length = tvb_length_remaining(tvb,0);
|
||||
|
@ -671,11 +676,11 @@ integer32_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
|||
return label;
|
||||
}
|
||||
|
||||
static const char*
|
||||
integer64_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
integer64_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
char* label;
|
||||
proto_item* pi;
|
||||
char *label;
|
||||
proto_item *pi;
|
||||
|
||||
/* Verify length before adding */
|
||||
gint length = tvb_length_remaining(tvb,0);
|
||||
|
@ -697,11 +702,11 @@ integer64_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
|||
return label;
|
||||
}
|
||||
|
||||
static const char*
|
||||
unsigned32_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
unsigned32_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
char* label;
|
||||
proto_item* pi;
|
||||
char *label;
|
||||
proto_item *pi;
|
||||
|
||||
/* Verify length before adding */
|
||||
gint length = tvb_length_remaining(tvb,0);
|
||||
|
@ -723,11 +728,11 @@ unsigned32_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
|||
return label;
|
||||
}
|
||||
|
||||
static const char*
|
||||
unsigned64_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
unsigned64_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
char* label;
|
||||
proto_item* pi;
|
||||
char *label;
|
||||
proto_item *pi;
|
||||
|
||||
/* Verify length before adding */
|
||||
gint length = tvb_length_remaining(tvb,0);
|
||||
|
@ -749,11 +754,11 @@ unsigned64_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
|||
return label;
|
||||
}
|
||||
|
||||
static const char*
|
||||
float32_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
float32_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
char* label;
|
||||
proto_item* pi;
|
||||
char *label;
|
||||
proto_item *pi;
|
||||
|
||||
/* Verify length before adding */
|
||||
gint length = tvb_length_remaining(tvb,0);
|
||||
|
@ -775,11 +780,11 @@ float32_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
|||
return label;
|
||||
}
|
||||
|
||||
static const char*
|
||||
float64_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
float64_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
char* label;
|
||||
proto_item* pi;
|
||||
char *label;
|
||||
proto_item *pi;
|
||||
|
||||
/* Verify length before adding */
|
||||
gint length = tvb_length_remaining(tvb,0);
|
||||
|
@ -801,13 +806,13 @@ float64_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
|||
return label;
|
||||
}
|
||||
|
||||
static const char*
|
||||
grouped_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
||||
static const char *
|
||||
grouped_avp(diam_ctx_t *c, diam_avp_t *a, tvbuff_t *tvb)
|
||||
{
|
||||
int offset = 0;
|
||||
int len = tvb_length(tvb);
|
||||
proto_item* pi = proto_tree_add_item(c->tree, a->hf_value, tvb , 0 , -1, ENC_BIG_ENDIAN);
|
||||
proto_tree* pt = c->tree;
|
||||
proto_item *pi = proto_tree_add_item(c->tree, a->hf_value, tvb , 0 , -1, ENC_BIG_ENDIAN);
|
||||
proto_tree *pt = c->tree;
|
||||
|
||||
c->tree = proto_item_add_subtree(pi,a->ett);
|
||||
|
||||
|
@ -821,7 +826,7 @@ grouped_avp(diam_ctx_t* c, diam_avp_t* a, tvbuff_t* tvb)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char* msgflags_str[] = {
|
||||
static const char *msgflags_str[] = {
|
||||
"----", "---T", "--E-", "--ET",
|
||||
"-P--", "-P-T", "-PE-", "-PET",
|
||||
"R---", "R--T", "R-E-", "R-ET",
|
||||
|
@ -829,7 +834,7 @@ static const char* msgflags_str[] = {
|
|||
};
|
||||
|
||||
static void
|
||||
dissect_diameter_common(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree)
|
||||
dissect_diameter_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
||||
{
|
||||
guint32 first_word = tvb_get_ntohl(tvb,0);
|
||||
guint32 version = (first_word & 0xff000000) >> 24;
|
||||
|
@ -843,10 +848,11 @@ dissect_diameter_common(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree)
|
|||
const char *cmd_str;
|
||||
guint32 cmd = tvb_get_ntoh24(tvb,5);
|
||||
guint32 fourth = tvb_get_ntohl(tvb,8);
|
||||
guint32 hop_by_hop_id = 0;
|
||||
guint32 hop_by_hop_id, end_to_end_id;
|
||||
conversation_t *conversation;
|
||||
diameter_conv_info_t *diameter_conv_info;
|
||||
diameter_req_ans_pair_t *diameter_pair;
|
||||
emem_tree_t *pdus_tree;
|
||||
proto_item *it;
|
||||
nstime_t ns;
|
||||
void *pd_save;
|
||||
|
@ -865,7 +871,7 @@ dissect_diameter_common(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree)
|
|||
|
||||
pi = proto_tree_add_item(diam_tree,hf_diameter_flags,tvb,4,1,ENC_BIG_ENDIAN);
|
||||
{
|
||||
proto_tree* pt = proto_item_add_subtree(pi,ett_diameter_flags);
|
||||
proto_tree *pt = proto_item_add_subtree(pi,ett_diameter_flags);
|
||||
proto_tree_add_item(pt,hf_diameter_flags_request,tvb,4,1,ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(pt,hf_diameter_flags_proxyable,tvb,4,1,ENC_BIG_ENDIAN);
|
||||
proto_tree_add_item(pt,hf_diameter_flags_error,tvb,4,1,ENC_BIG_ENDIAN);
|
||||
|
@ -885,7 +891,7 @@ dissect_diameter_common(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree)
|
|||
switch (version) {
|
||||
case DIAMETER_V16: {
|
||||
guint32 vendorid = tvb_get_ntohl(tvb,8);
|
||||
diam_vnd_t* vendor;
|
||||
diam_vnd_t *vendor;
|
||||
|
||||
if (! ( vendor = emem_tree_lookup32(dictionary.vnds,vendorid) ) ) {
|
||||
vendor = &unknown_vendor;
|
||||
|
@ -901,7 +907,7 @@ dissect_diameter_common(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree)
|
|||
/* Store the application id to be used by subdissectors */
|
||||
pinfo->private_data = &fourth;
|
||||
|
||||
cmd_vs = (value_string*)(void*)all_cmds->data;
|
||||
cmd_vs = (value_string *)(void *)all_cmds->data;
|
||||
|
||||
app_item = proto_tree_add_item(diam_tree, hf_diameter_application_id, tvb, 8, 4, ENC_BIG_ENDIAN);
|
||||
if (match_strval(fourth, dictionary.applications) == NULL) {
|
||||
|
@ -918,8 +924,8 @@ dissect_diameter_common(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree)
|
|||
}
|
||||
default:
|
||||
{
|
||||
proto_tree* pt = proto_item_add_subtree(version_item,ett_err);
|
||||
proto_item* pi_local = proto_tree_add_text(pt,tvb,0,1,"Unknown Diameter Version (decoding as RFC 3588)");
|
||||
proto_tree *pt = proto_item_add_subtree(version_item,ett_err);
|
||||
proto_item *pi_local = proto_tree_add_text(pt,tvb,0,1,"Unknown Diameter Version (decoding as RFC 3588)");
|
||||
expert_add_info_format(pinfo, pi_local, PI_UNDECODED, PI_WARN, "Unknown Diameter Version");
|
||||
PROTO_ITEM_SET_GENERATED(pi);
|
||||
c->version_rfc = TRUE;
|
||||
|
@ -944,8 +950,8 @@ dissect_diameter_common(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree)
|
|||
/* Append name to command item, warn if unknown */
|
||||
proto_item_append_text(cmd_item," %s", cmd_str);
|
||||
if (strcmp(cmd_str, "Unknown") == 0) {
|
||||
proto_tree* tu = proto_item_add_subtree(cmd_item,ett_unknown);
|
||||
proto_item* iu = proto_tree_add_text(tu,tvb, 5 ,3,"Unknown command, "
|
||||
proto_tree *tu = proto_item_add_subtree(cmd_item,ett_unknown);
|
||||
proto_item *iu = proto_tree_add_text(tu,tvb, 5 ,3,"Unknown command, "
|
||||
"if you know what this is you can add it to dictionary.xml");
|
||||
expert_add_info_format(c->pinfo, iu, PI_UNDECODED, PI_WARN, "Unknown command (%u)", cmd);
|
||||
PROTO_ITEM_SET_GENERATED(iu);
|
||||
|
@ -954,6 +960,7 @@ dissect_diameter_common(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree)
|
|||
|
||||
hop_by_hop_id = tvb_get_ntohl(tvb, 12);
|
||||
proto_tree_add_item(diam_tree,hf_diameter_hopbyhopid,tvb,12,4,ENC_BIG_ENDIAN);
|
||||
end_to_end_id = tvb_get_ntohl(tvb, 16);
|
||||
proto_tree_add_item(diam_tree,hf_diameter_endtoendid,tvb,16,4,ENC_BIG_ENDIAN);
|
||||
|
||||
/* Conversation tracking stuff */
|
||||
|
@ -967,32 +974,57 @@ dissect_diameter_common(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree)
|
|||
diameter_conv_info = conversation_get_proto_data(conversation, proto_diameter);
|
||||
if (!diameter_conv_info) {
|
||||
diameter_conv_info = se_alloc(sizeof(diameter_conv_info_t));
|
||||
diameter_conv_info->pdus = se_tree_create_non_persistent(
|
||||
EMEM_TREE_TYPE_RED_BLACK, "diameter_pdus");
|
||||
diameter_conv_info->pdus_tree = se_tree_create_non_persistent(
|
||||
EMEM_TREE_TYPE_RED_BLACK, "diameter_pdu_trees");
|
||||
|
||||
conversation_add_proto_data(conversation, proto_diameter, diameter_conv_info);
|
||||
}
|
||||
|
||||
if (!pinfo->fd->flags.visited) {
|
||||
if (flags_bits & DIAM_FLAGS_R) {
|
||||
/* This is a request */
|
||||
diameter_pair = se_alloc(sizeof(diameter_req_ans_pair_t));
|
||||
diameter_pair->hop_by_hop_id = hop_by_hop_id;
|
||||
diameter_pair->cmd_code = cmd;
|
||||
diameter_pair->result_code = 0;
|
||||
diameter_pair->cmd_str = cmd_str;
|
||||
diameter_pair->req_frame = PINFO_FD_NUM(pinfo);
|
||||
diameter_pair->ans_frame = 0;
|
||||
diameter_pair->req_time = pinfo->fd->abs_ts;
|
||||
se_tree_insert32(diameter_conv_info->pdus, hop_by_hop_id, (void *)diameter_pair);
|
||||
} else {
|
||||
diameter_pair = se_tree_lookup32(diameter_conv_info->pdus, hop_by_hop_id);
|
||||
if (diameter_pair) {
|
||||
diameter_pair->ans_frame = PINFO_FD_NUM(pinfo);
|
||||
}
|
||||
}
|
||||
/* pdus_tree is an se_tree keyed by frame number (in order to handle hop-by-hop collisions */
|
||||
pdus_tree = se_tree_lookup32(diameter_conv_info->pdus_tree, hop_by_hop_id);
|
||||
|
||||
if (pdus_tree == NULL && (flags_bits & DIAM_FLAGS_R)) {
|
||||
/* This is the first request we've seen with this hop-by-hop id */
|
||||
pdus_tree = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "diameter_pdus");
|
||||
se_tree_insert32(diameter_conv_info->pdus_tree, hop_by_hop_id, pdus_tree);
|
||||
} else {
|
||||
diameter_pair = se_tree_lookup32(diameter_conv_info->pdus, hop_by_hop_id);
|
||||
/* If we found nothing with this Answer's hop-by-hop-id then we're done. */
|
||||
diameter_pair = NULL;
|
||||
}
|
||||
|
||||
if (pdus_tree) {
|
||||
if (!pinfo->fd->flags.visited) {
|
||||
if (flags_bits & DIAM_FLAGS_R) {
|
||||
/* This is a request */
|
||||
diameter_pair = se_alloc(sizeof(diameter_req_ans_pair_t));
|
||||
diameter_pair->hop_by_hop_id = hop_by_hop_id;
|
||||
diameter_pair->end_to_end_id = end_to_end_id;
|
||||
diameter_pair->cmd_code = cmd;
|
||||
diameter_pair->result_code = 0;
|
||||
diameter_pair->cmd_str = cmd_str;
|
||||
diameter_pair->req_frame = PINFO_FD_NUM(pinfo);
|
||||
diameter_pair->ans_frame = 0;
|
||||
diameter_pair->req_time = pinfo->fd->abs_ts;
|
||||
se_tree_insert32(pdus_tree, PINFO_FD_NUM(pinfo), (void *)diameter_pair);
|
||||
} else {
|
||||
/* Look for a request which occurs earlier in the trace than this answer. */
|
||||
diameter_pair = se_tree_lookup32_le(pdus_tree, PINFO_FD_NUM(pinfo));
|
||||
|
||||
/* Verify the end-to-end-id matches before declaring a match */
|
||||
if (diameter_pair && diameter_pair->end_to_end_id == end_to_end_id) {
|
||||
diameter_pair->ans_frame = PINFO_FD_NUM(pinfo);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Look for a request which occurs earlier in the trace than this answer. */
|
||||
diameter_pair = se_tree_lookup32_le(pdus_tree, PINFO_FD_NUM(pinfo));
|
||||
|
||||
/* If the end-to-end ID doesn't match then this is not the request we were
|
||||
* looking for.
|
||||
*/
|
||||
if (diameter_pair && diameter_pair->end_to_end_id != end_to_end_id)
|
||||
diameter_pair = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!diameter_pair) {
|
||||
|
@ -1105,11 +1137,11 @@ dissect_diameter_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
|
|||
}
|
||||
|
||||
|
||||
static char*
|
||||
alnumerize(char* name)
|
||||
static char *
|
||||
alnumerize(char *name)
|
||||
{
|
||||
char* r = name;
|
||||
char* w = name;
|
||||
char *r = name;
|
||||
char *w = name;
|
||||
char c;
|
||||
|
||||
for (;(c = *r); r++) {
|
||||
|
@ -1125,8 +1157,8 @@ alnumerize(char* name)
|
|||
|
||||
|
||||
static guint
|
||||
reginfo(int* hf_ptr, const char* name, const char* abbr, const char* desc,
|
||||
enum ftenum ft, base_display_e base, value_string_ext* vs_ext,
|
||||
reginfo(int *hf_ptr, const char *name, const char *abbr, const char *desc,
|
||||
enum ftenum ft, base_display_e base, value_string_ext *vs_ext,
|
||||
guint32 mask)
|
||||
{
|
||||
hf_register_info hf = { hf_ptr, {
|
||||
|
@ -1148,8 +1180,8 @@ reginfo(int* hf_ptr, const char* name, const char* abbr, const char* desc,
|
|||
}
|
||||
|
||||
static void
|
||||
basic_avp_reginfo(diam_avp_t* a, const char* name, enum ftenum ft,
|
||||
base_display_e base, value_string_ext* vs_ext)
|
||||
basic_avp_reginfo(diam_avp_t *a, const char *name, enum ftenum ft,
|
||||
base_display_e base, value_string_ext *vs_ext)
|
||||
{
|
||||
hf_register_info hf[] = { { &(a->hf_value),
|
||||
{ NULL, NULL, ft, base, NULL, 0x0,
|
||||
|
@ -1158,7 +1190,7 @@ basic_avp_reginfo(diam_avp_t* a, const char* name, enum ftenum ft,
|
|||
: g_strdup_printf("code=%d", a->code),
|
||||
HFILL }}
|
||||
};
|
||||
gint* ettp = &(a->ett);
|
||||
gint *ettp = &(a->ett);
|
||||
|
||||
hf->hfinfo.name = g_strdup_printf("%s",name);
|
||||
hf->hfinfo.abbrev = alnumerize(g_strdup_printf("diameter.%s",name));
|
||||
|
@ -1170,14 +1202,14 @@ basic_avp_reginfo(diam_avp_t* a, const char* name, enum ftenum ft,
|
|||
g_ptr_array_add(build_dict.ett,ettp);
|
||||
}
|
||||
|
||||
static diam_avp_t*
|
||||
build_address_avp(const avp_type_t* type _U_, guint32 code,
|
||||
const diam_vnd_t* vendor, const char* name,
|
||||
const value_string* vs _U_, void* data _U_)
|
||||
static diam_avp_t *
|
||||
build_address_avp(const avp_type_t *type _U_, guint32 code,
|
||||
const diam_vnd_t *vendor, const char *name,
|
||||
const value_string *vs _U_, void *data _U_)
|
||||
{
|
||||
diam_avp_t* a = g_malloc0(sizeof(diam_avp_t));
|
||||
address_avp_t* t = g_malloc(sizeof(address_avp_t));
|
||||
gint* ettp = &(t->ett);
|
||||
diam_avp_t *a = g_malloc0(sizeof(diam_avp_t));
|
||||
address_avp_t *t = g_malloc(sizeof(address_avp_t));
|
||||
gint *ettp = &(t->ett);
|
||||
|
||||
a->code = code;
|
||||
a->vendor = vendor;
|
||||
|
@ -1243,14 +1275,14 @@ RFC3588
|
|||
return a;
|
||||
}
|
||||
|
||||
static diam_avp_t*
|
||||
build_proto_avp(const avp_type_t* type _U_, guint32 code,
|
||||
const diam_vnd_t* vendor, const char* name _U_,
|
||||
const value_string* vs _U_, void* data)
|
||||
static diam_avp_t *
|
||||
build_proto_avp(const avp_type_t *type _U_, guint32 code,
|
||||
const diam_vnd_t *vendor, const char *name _U_,
|
||||
const value_string *vs _U_, void *data)
|
||||
{
|
||||
diam_avp_t* a = g_malloc0(sizeof(diam_avp_t));
|
||||
proto_avp_t* t = g_malloc0(sizeof(proto_avp_t));
|
||||
gint* ettp = &(a->ett);
|
||||
diam_avp_t *a = g_malloc0(sizeof(diam_avp_t));
|
||||
proto_avp_t *t = g_malloc0(sizeof(proto_avp_t));
|
||||
gint *ettp = &(a->ett);
|
||||
|
||||
a->code = code;
|
||||
a->vendor = vendor;
|
||||
|
@ -1269,11 +1301,11 @@ build_proto_avp(const avp_type_t* type _U_, guint32 code,
|
|||
return a;
|
||||
}
|
||||
|
||||
static diam_avp_t*
|
||||
build_simple_avp(const avp_type_t* type, guint32 code, const diam_vnd_t* vendor,
|
||||
const char* name, const value_string* vs, void* data _U_)
|
||||
static diam_avp_t *
|
||||
build_simple_avp(const avp_type_t *type, guint32 code, const diam_vnd_t *vendor,
|
||||
const char *name, const value_string *vs, void *data _U_)
|
||||
{
|
||||
diam_avp_t* a;
|
||||
diam_avp_t *a;
|
||||
value_string_ext *vs_ext = NULL;
|
||||
base_display_e base;
|
||||
guint i = 0;
|
||||
|
@ -1301,7 +1333,7 @@ build_simple_avp(const avp_type_t* type, guint32 code, const diam_vnd_t* vendor,
|
|||
while (vs[i].strptr) {
|
||||
i++;
|
||||
}
|
||||
vs_ext = value_string_ext_new((void*)vs, i+1, g_strdup_printf("%s_vals_ext",name));
|
||||
vs_ext = value_string_ext_new((void *)vs, i+1, g_strdup_printf("%s_vals_ext",name));
|
||||
base = base|BASE_EXT_STRING;
|
||||
}
|
||||
|
||||
|
@ -1379,8 +1411,8 @@ strcase_hash(gconstpointer key)
|
|||
static gboolean
|
||||
strcase_equal(gconstpointer ka, gconstpointer kb)
|
||||
{
|
||||
const char* a = ka;
|
||||
const char* b = kb;
|
||||
const char *a = ka;
|
||||
const char *b = kb;
|
||||
return g_ascii_strcasecmp(a,b) == 0;
|
||||
}
|
||||
|
||||
|
@ -1393,21 +1425,21 @@ strcase_equal(gconstpointer ka, gconstpointer kb)
|
|||
static int
|
||||
dictionary_load(void)
|
||||
{
|
||||
ddict_t* d;
|
||||
ddict_application_t* p;
|
||||
ddict_vendor_t* v;
|
||||
ddict_cmd_t* c;
|
||||
ddict_typedefn_t* t;
|
||||
ddict_avp_t* a;
|
||||
ddict_t *d;
|
||||
ddict_application_t *p;
|
||||
ddict_vendor_t *v;
|
||||
ddict_cmd_t *c;
|
||||
ddict_typedefn_t *t;
|
||||
ddict_avp_t *a;
|
||||
gboolean do_debug_parser = getenv("WIRESHARK_DEBUG_DIAM_DICT_PARSER") ? TRUE : FALSE;
|
||||
gboolean do_dump_dict = getenv("WIRESHARK_DUMP_DIAM_DICT") ? TRUE : FALSE;
|
||||
char* dir = ep_strdup_printf("%s" G_DIR_SEPARATOR_S "diameter" G_DIR_SEPARATOR_S, get_datafile_dir());
|
||||
const avp_type_t* type;
|
||||
const avp_type_t* octetstring = &basic_types[0];
|
||||
diam_avp_t* avp;
|
||||
GHashTable* vendors = g_hash_table_new(strcase_hash,strcase_equal);
|
||||
diam_vnd_t* vnd;
|
||||
GArray* vnd_shrt_arr = g_array_new(TRUE,TRUE,sizeof(value_string));
|
||||
char *dir = ep_strdup_printf("%s" G_DIR_SEPARATOR_S "diameter" G_DIR_SEPARATOR_S, get_datafile_dir());
|
||||
const avp_type_t *type;
|
||||
const avp_type_t *octetstring = &basic_types[0];
|
||||
diam_avp_t *avp;
|
||||
GHashTable *vendors = g_hash_table_new(strcase_hash,strcase_equal);
|
||||
diam_vnd_t *vnd;
|
||||
GArray *vnd_shrt_arr = g_array_new(TRUE,TRUE,sizeof(value_string));
|
||||
|
||||
build_dict.hf = g_array_new(FALSE,TRUE,sizeof(hf_register_info));
|
||||
build_dict.ett = g_ptr_array_new();
|
||||
|
@ -1429,7 +1461,7 @@ dictionary_load(void)
|
|||
|
||||
/* initialize the types hash with the known basic types */
|
||||
for (type = basic_types; type->name; type++) {
|
||||
g_hash_table_insert(build_dict.types,(gchar *)type->name,(void*)type);
|
||||
g_hash_table_insert(build_dict.types,(gchar *)type->name,(void *)type);
|
||||
}
|
||||
|
||||
/* load the dictionary */
|
||||
|
@ -1442,7 +1474,7 @@ dictionary_load(void)
|
|||
|
||||
/* populate the types */
|
||||
for (t = d->typedefns; t; t = t->next) {
|
||||
const avp_type_t* parent = NULL;
|
||||
const avp_type_t *parent = NULL;
|
||||
/* try to get the parent type */
|
||||
|
||||
if (t->name == NULL) {
|
||||
|
@ -1462,19 +1494,19 @@ dictionary_load(void)
|
|||
if (!parent) parent = octetstring;
|
||||
|
||||
/* insert the parent type for this type */
|
||||
g_hash_table_insert(build_dict.types,t->name,(void*)parent);
|
||||
g_hash_table_insert(build_dict.types,t->name,(void *)parent);
|
||||
}
|
||||
|
||||
/* populate the applications */
|
||||
if ((p = d->applications)) {
|
||||
GArray* arr = g_array_new(TRUE,TRUE,sizeof(value_string));
|
||||
GArray *arr = g_array_new(TRUE,TRUE,sizeof(value_string));
|
||||
|
||||
for (; p; p = p->next) {
|
||||
value_string item = {p->code,p->name};
|
||||
g_array_append_val(arr,item);
|
||||
}
|
||||
|
||||
dictionary.applications = (void*)arr->data;
|
||||
dictionary.applications = (void *)arr->data;
|
||||
g_array_free(arr,FALSE);
|
||||
}
|
||||
|
||||
|
@ -1502,7 +1534,7 @@ dictionary_load(void)
|
|||
}
|
||||
}
|
||||
|
||||
vnd_short_vs = (void*)vnd_shrt_arr->data;
|
||||
vnd_short_vs = (void *)vnd_shrt_arr->data;
|
||||
g_array_free(vnd_shrt_arr,FALSE);
|
||||
|
||||
if ((c = d->cmds)) {
|
||||
|
@ -1526,11 +1558,11 @@ dictionary_load(void)
|
|||
|
||||
|
||||
for (a = d->avps; a; a = a->next) {
|
||||
ddict_enum_t* e;
|
||||
value_string* vs = NULL;
|
||||
const char* vend = a->vendor ? a->vendor : "None";
|
||||
ddict_xmlpi_t* x;
|
||||
void* avp_data = NULL;
|
||||
ddict_enum_t *e;
|
||||
value_string *vs = NULL;
|
||||
const char *vend = a->vendor ? a->vendor : "None";
|
||||
ddict_xmlpi_t *x;
|
||||
void *avp_data = NULL;
|
||||
|
||||
if (a->name == NULL) {
|
||||
fprintf(stderr,"Diameter Dictionary: Invalid AVP (empty name)\n");
|
||||
|
@ -1546,14 +1578,14 @@ dictionary_load(void)
|
|||
}
|
||||
|
||||
if ((e = a->enums)) {
|
||||
GArray* arr = g_array_new(TRUE,TRUE,sizeof(value_string));
|
||||
GArray *arr = g_array_new(TRUE,TRUE,sizeof(value_string));
|
||||
|
||||
for (; e; e = e->next) {
|
||||
value_string item = {e->code,e->name};
|
||||
g_array_append_val(arr,item);
|
||||
}
|
||||
g_array_sort(arr, compare_avps);
|
||||
vs = (void*)arr->data;
|
||||
vs = (void *)arr->data;
|
||||
}
|
||||
|
||||
type = NULL;
|
||||
|
@ -1770,8 +1802,8 @@ real_proto_register_diameter(void)
|
|||
|
||||
proto_diameter = proto_register_protocol ("Diameter Protocol", "DIAMETER", "diameter");
|
||||
|
||||
proto_register_field_array(proto_diameter, (hf_register_info*)(void*)build_dict.hf->data, build_dict.hf->len);
|
||||
proto_register_subtree_array((gint**)build_dict.ett->pdata, build_dict.ett->len);
|
||||
proto_register_field_array(proto_diameter, (hf_register_info *)(void *)build_dict.hf->data, build_dict.hf->len);
|
||||
proto_register_subtree_array((gint **)build_dict.ett->pdata, build_dict.ett->len);
|
||||
|
||||
g_array_free(build_dict.hf,FALSE);
|
||||
g_ptr_array_free(build_dict.ett,TRUE);
|
||||
|
|
Loading…
Reference in New Issue