forked from osmocom/wireshark
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:
parent
12e2df52e1
commit
e3a0cf1fcb
|
@ -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">
|
||||
|
|
|
@ -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"/>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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){
|
||||
|
|
Loading…
Reference in New Issue