From Andrej Kuehnal:

tap-diameter-avp.patch:
- make diameter.cmd_code configurable rather than hard coded in 
- more fields in the output
- documetation/man pages + usage examples
- switch option parser from stdlib to glib to avoid troubles with M$ c++

diameter-dict.patch
remove strage spaces in the AVP names.

svn path=/trunk/; revision=32294
This commit is contained in:
Anders Broman 2010-03-26 20:15:55 +00:00
parent 12e2df52e1
commit e3a0cf1fcb
4 changed files with 99 additions and 48 deletions

View File

@ -58,7 +58,7 @@
<avp name="3GPP-IPv6-DNS-Server" code="17" mandatory="must" may-encrypt="yes" protected="may" vendor-bit="must" vendor-id="TGPP">
<type type-name="OctetString"/>
</avp>
<avp name="3GPP-SGSN MCC-MNC" code="18" mandatory="must" may-encrypt="yes" protected="may" vendor-bit="must" vendor-id="TGPP">
<avp name="3GPP-SGSN-MCC-MNC" code="18" mandatory="must" may-encrypt="yes" protected="may" vendor-bit="must" vendor-id="TGPP">
<type type-name="UTF8String"/>
</avp>
<avp name="3GPP-Teardown Indicator" code="19" mandatory="must" may-encrypt="yes" protected="may" vendor-bit="must" vendor-id="TGPP">

View File

@ -1943,7 +1943,7 @@ Note: The AVP codes from 800 to 822 are reserved for TS 32.299.
<gavp name="GGSN-Address"/>
<gavp name="CG-Address"/>
<gavp name="3GPP-IMSI-MCC-MNC"/>
<gavp name="3GPP-GGSN- MCC-MNC"/>
<gavp name="3GPP-GGSN-MCC-MNC"/>
<gavp name="3GPP-NSAPI"/>
<gavp name="Called-Station-Id"/>
<gavp name="3GPP-Session-Stop-Indicator"/>

View File

@ -671,6 +671,49 @@ B<-z "proto,colinfo,nfs.fh.hash && ip.src==1.2.3.4,nfs.fh.hash">
This option can be used multiple times on the command line.
=item B<-z> diameter,avp[,I<cmd.code>,I<field>,I<field>,I<...>]
This option enables extraction of most important diameter fields from large capture files.
Exactly one text line for each diameter message with matched B<diameter.cmd.code> will be printed.
Empty diameter command code or '*' can be specified to mach any B<diameter.cmd.code>
Example: B<-z diameter,avp> extract default field set from diameter messages.
Example: B<-z diameter,avp,280> extract default field set from diameter DWR messages.
Example: B<-z diameter,avp,272> extract default field set from diameter CC messages.
Extract most important fields from diameter CC messages:
B<tshark -r file.cap.gz -q -z diameter,avp,272,CC-Request-Type,CC-Request-Number,Session-Id,Subscription-Id-Data,Rating-Group,Result-Code>
Following fields will be printed out for each diameter message:
"frame" Frame number.
"time" Unix time of the frame arrival.
"src" Source address.
"srcport" Source port.
"dst" Destination address.
"dstport" Destination port.
"proto" Constant string 'diameter', which can be used for post processing of tshark output. e.g. grep/sed/awk.
"msgnr" seq. number of diameter message within the frame. E.g. '2' for the third diameter message in the same frame.
"is_request" '0' if message is a request, '1' if message is an answer.
"cmd" diameter.cmd_code, E.g. '272' for credit control messages.
"req_frame" Number of frame where matched request was found or '0'.
"ans_frame" Number of frame where matched answer was found or '0'.
"resp_time" response time in seconds, '0' in case if matched Request/Answer is not found in trace. E.g. in the begin or end of capture.
B<-z diameter,avp> option is much faster than B<-V -T text> or B<-T pdml> options.
B<-z diameter,avp> option is more powerful than B<-T field> and B<-z proto,colinfo> options.
Multiple diameter messages in one frame are supported.
Several fields with same name within one diameter message are supported, e.g. I<diameter.Subscription-Id-Data> or I<diameter.Rating-Group>.
Note: B<tshark -q> option is recommended to suppress default B<tshark> output.
=item B<-z> rpc,rtt,I<program>,I<version>[,I<filter>]
Collect call/reply RTT data for I<program>/I<version>. Data collected

View File

@ -55,17 +55,19 @@
#include "epan/nstime.h"
#include "epan/ftypes/ftypes.h"
#include "register.h"
#include <epan/dissectors/packet-diameter.h>
#include "epan/to_str.h"
#include "epan/dissectors/packet-diameter.h"
/* used to keep track of the statistics for an entire program interface */
typedef struct _diameteravp_t {
guint32 frame;
guint32 diammsg_toprocess;
guint32 cmd_code;
guint32 req_count;
guint32 ans_count;
guint32 paired_ans_count;
char* filter;
gchar* filter;
} diameteravp_t;
/* Copied from proto.c */
@ -98,13 +100,13 @@ diam_tree_to_csv(proto_node* node, gpointer data)
field_info* fi;
header_field_info *hfi;
if(!node) {
fprintf(stderr,"traverse end: node='%p' data='%p'\n",node,data);
fprintf(stderr,"traverse end: empty node. node='%p' data='%p'\n",node,data);
return FALSE;
}
fi=node->finfo;
hfi=fi ? fi->hfinfo : NULL;
if(!hfi) {
fprintf(stderr,"traverse end2: Hfi not found node='%p'\n",node);
fprintf(stderr,"traverse end: hfi not found. node='%p'\n",node);
return FALSE;
}
ftype=fi->value.ftype->ftype;
@ -144,32 +146,39 @@ diameteravp_packet(void *pds, packet_info *pinfo, epan_dissect_t *edt _U_, const
header_field_info* hfi=NULL;
field_info* finfo=NULL;
const diameter_req_ans_pair_t* dp=pdi;
diameteravp_t *ds=NULL;
/* Validate paramerers. */
if(!dp || !edt || !edt->tree)
return ret;
/* Several diameter messages within one frame are possible. *
* Check if we processing the message in same frame like befor or in new frame.*/
diameteravp_t *ds=(diameteravp_t *)pds;
ds=(diameteravp_t *)pds;
if(pinfo->fd->num > ds->frame) {
ds->frame=pinfo->fd->num;
ds->diammsg_toprocess=0;
} else {
ds->diammsg_toprocess+=1;
}
/* Extract data from request/answer pair provided by diameter dissector.*/
if(dp) {
is_request=dp->processing_request;
cmd_code=dp->cmd_code;
result_code=dp->result_code;
req_frame=dp->req_frame;
ans_frame=dp->ans_frame;
if(!is_request) {
nstime_t ns;
nstime_delta(&ns, &pinfo->fd->abs_ts, &dp->req_time);
resp_time=nstime_to_sec(&ns);
resp_time=resp_time<0?0.:resp_time;
}
is_request=dp->processing_request;
cmd_code=dp->cmd_code;
result_code=dp->result_code;
req_frame=dp->req_frame;
ans_frame=dp->ans_frame;
if(!is_request) {
nstime_t ns;
nstime_delta(&ns, &pinfo->fd->abs_ts, &dp->req_time);
resp_time=nstime_to_sec(&ns);
resp_time=resp_time<0?0.:resp_time;
}
if (!edt || !edt->tree || cmd_code!=272)
/* Check command code provided by command line option.*/
if (ds->cmd_code && ds->cmd_code!=cmd_code)
return ret;
/* Loop over top level nodes */
node = edt->tree->first_child;
while (node != NULL) {
@ -177,7 +186,7 @@ diameteravp_packet(void *pds, packet_info *pinfo, epan_dissect_t *edt _U_, const
node = current->next;
finfo=current->finfo;
hfi=finfo ? finfo->hfinfo : NULL;
/*fprintf(stderr,"diameteravp_packet %d %p %p node=%p abbrev=%s\n",cmd_code,edt,edt->tree,current,hfi->abbrev);*/
/*fprintf(stderr,"DEBUG: diameteravp_packet %d %p %p node=%p abbrev=%s\n",cmd_code,edt,edt->tree,current,hfi->abbrev);*/
/* process current diameter subtree in the current frame. */
if(hfi && hfi->abbrev && strcmp(hfi->abbrev,"diameter")==0) {
/* Process current diameter message in the frame */
@ -190,7 +199,8 @@ diameteravp_packet(void *pds, packet_info *pinfo, epan_dissect_t *edt _U_, const
ds->paired_ans_count++;
}
/* Output frame data.*/
printf("frame='%d' proto='diameter' msgnr='%d' is_request='%d' cmd='%d' req_frame='%d' ans_frame='%d' resp_time='%f' ",pinfo->fd->num,ds->diammsg_toprocess,is_request,cmd_code,req_frame,ans_frame,resp_time);
printf("frame='%d' time='%f' src='%s' srcport='%d' dst='%s' dstport='%d' proto='diameter' msgnr='%d' is_request='%d' cmd='%d' req_frame='%d' ans_frame='%d' resp_time='%f' ",
pinfo->fd->num,nstime_to_sec(&pinfo->fd->abs_ts),ep_address_to_str(&pinfo->src),pinfo->srcport,ep_address_to_str(&pinfo->dst), pinfo->destport,ds->diammsg_toprocess,is_request,cmd_code,req_frame,ans_frame,resp_time);
/* Visit selected nodes of one diameter message.*/
tree_traverse_pre_order(current, diam_tree_to_csv, &ds);
/* End of message.*/
@ -216,47 +226,45 @@ static void
diameteravp_init(const char *optarg, void* userdata _U_)
{
diameteravp_t *ds;
char* options=NULL;
char* saveptr=NULL;
char* str=NULL;
int field_count=0;
size_t filter_len=0;
GString *error_string;
gchar* field=NULL;
gchar** tokens;
guint opt_count=0;
guint opt_idx=0;
GString* filter=NULL;
GString* error_string=NULL;
ds=g_malloc(sizeof(diameteravp_t));
ds->frame=0;
ds->diammsg_toprocess=0;
ds->cmd_code=0;
ds->req_count=0;
ds->ans_count=0;
ds->paired_ans_count=0;
str=NULL;
ds->filter=NULL;
options=g_strdup(optarg);
for(str=options;*str;str++)
{
if(*str==',')
field_count++;
}
filter_len=strlen(optarg)+sizeof("diameter")+field_count*sizeof("||diameter.");
ds->filter=g_malloc0(filter_len);
g_strlcat(ds->filter, "diameter", filter_len);
filter=g_string_new("diameter");
#if defined (_WIN32)
for(str=strtok_s(options+sizeof("diameter,avp"),",",&saveptr);str;str=strtok_s(NULL,",",&saveptr))
#else
for(str=strtok_r(options+sizeof("diameter,avp"),",",&saveptr);str;str=strtok_r(NULL,",",&saveptr))
#endif
/* Split command line options. */
tokens = g_strsplit(optarg,",", 1024);
opt_count=g_strv_length(tokens);
if (opt_count>2)
ds->cmd_code=(guint32)atoi(tokens[2]);
/* Loop over diameter field names. */
for(opt_idx=3;opt_idx<opt_count;opt_idx++)
{
/* Current field from command line arguments. */
field=tokens[opt_idx];
/* Connect all requested fields with logical OR. */
g_strlcat(ds->filter, "||", filter_len);
g_string_append(filter,"||");
/* Prefix field name with "diameter." by default. */
if(!strchr(str,'.'))
g_strlcat(ds->filter, "diameter.", filter_len);
if(!strchr(field,'.'))
g_string_append(filter, "diameter.");
/* Append field name to the filter. */
g_strlcat(ds->filter, str, filter_len);
g_string_append(filter, field);
}
g_free(options);
g_strfreev(tokens);
ds->filter=g_string_free(filter,FALSE);
error_string=register_tap_listener("diameter", ds, ds->filter, 0, NULL, diameteravp_packet, diameteravp_draw);
if(error_string){