Further cleanup of the document
svn path=/trunk/; revision=20855
This commit is contained in:
parent
7164abe385
commit
a6817744ae
|
@ -1,49 +1,50 @@
|
|||
$Id$
|
||||
|
||||
1. Introduction
|
||||
|
||||
It is often useful to enhance dissectors for request/response style protocols
|
||||
to match requests with responses.
|
||||
This allows you to display useful information in the decode tree
|
||||
such as which requests are matched to which response and the response time
|
||||
for individual transactions.
|
||||
This allows you to display useful information in the decode tree such as which
|
||||
requests are matched to which response and the response time for individual
|
||||
transactions.
|
||||
|
||||
This is also useful if you want to pass some data from the request onto the
|
||||
dissection of the actual response. The RPC dissector for example does
|
||||
something like this to pass the actual command opcode from the request
|
||||
onto the response dissector since the opcode itself is not part of the
|
||||
response packet and without the opcode we would not know how to decode the
|
||||
data.
|
||||
something like this to pass the actual command opcode from the request onto
|
||||
the response dissector since the opcode itself is not part of the response
|
||||
packet and without the opcode we would not know how to decode the data.
|
||||
|
||||
It is also useful when you need to track information on a per conversation
|
||||
basis such as when some parameters are negotiated during a login phase of the
|
||||
protocol and when these parameters affect how future commands on that
|
||||
session are to be decoded. The iSCSI dissector does something similar to that
|
||||
to track which sessions that HeaderDigest is activated for and which ones
|
||||
it is not.
|
||||
protocol and when these parameters affect how future commands on that session
|
||||
are to be decoded. The iSCSI dissector does something similar to that to track
|
||||
which sessions that HeaderDigest is activated for and which ones it is not.
|
||||
|
||||
2. Implementation
|
||||
|
||||
The example below shows how simple this is to add to the dissector IF:
|
||||
1. there is something like a transaction id in the header,
|
||||
2. it is very unlikely that the transaction identifier is reused for the
|
||||
same conversation.
|
||||
|
||||
The example is taken from the PANA dissector:
|
||||
|
||||
The example below shows how simple this is to add to the dissector IF
|
||||
1, there is something like a transaction id in the header
|
||||
2, it is very unlikely that the transaction identifier is reused for the same conversation
|
||||
|
||||
The example is taken from the PANA dissector :
|
||||
|
||||
|
||||
First we need to include the definitions for conversations and memory
|
||||
management
|
||||
First we need to include the definitions for conversations and memory
|
||||
management.
|
||||
|
||||
#include <epan/conversation.h>
|
||||
#include <epan/emem.h>
|
||||
|
||||
Then we also need a few header fields to show the relations between request
|
||||
and response as well as the response time
|
||||
and response as well as the response time.
|
||||
|
||||
static int hf_pana_response_in = -1;
|
||||
static int hf_pana_response_to = -1;
|
||||
static int hf_pana_time = -1;
|
||||
|
||||
We need a structure that holds all the information we need to remember
|
||||
between the request and the responses.
|
||||
One such structure will be allocated for each unique transaction.
|
||||
We need a structure that holds all the information we need to remember
|
||||
between the request and the responses. One such structure will be allocated
|
||||
for each unique transaction.
|
||||
In the example we only keep the frame numbers of the request and the response
|
||||
as well as the timestamp for the request.
|
||||
But since this structure is persistent and also a unique one is allocated for
|
||||
|
@ -57,8 +58,9 @@ data you may want to keep track of from a request to a response.
|
|||
} pana_transaction_t;
|
||||
|
||||
We also need a structure that holds persistent information for each
|
||||
conversation. ( a conversation is identified by SRC/DST address, protocol and SRC/DST port)
|
||||
In this case we only want to have keep a binary tree to track the actual
|
||||
conversation. A conversation is identified by SRC/DST address, protocol and
|
||||
SRC/DST port, see README.developer.
|
||||
In this case we only want to have a binary tree to track the actual
|
||||
transactions that occur for this unique conversation.
|
||||
Some protocols negotiate session parameters during a login phase and those
|
||||
parameters may affect how later commands on the same session is to be decoded,
|
||||
|
@ -69,10 +71,8 @@ around.
|
|||
emem_tree_t *pdus;
|
||||
} pana_conv_info_t;
|
||||
|
||||
|
||||
|
||||
Finally for the meat of it, add the conversation and tracking code to the
|
||||
actual dissector
|
||||
Finally for the meat of it, add the conversation and tracking code to the
|
||||
actual dissector.
|
||||
|
||||
...
|
||||
guint32 seq_num;
|
||||
|
@ -108,69 +108,68 @@ actual dissector
|
|||
*/
|
||||
pana_info = conversation_get_proto_data(conversation, proto_pana);
|
||||
if (!pana_info) {
|
||||
/* No. Attach that information to the conversation, and add
|
||||
/*
|
||||
* No. Attach that information to the conversation, and add
|
||||
* it to the list of information structures.
|
||||
*/
|
||||
pana_info = se_alloc(sizeof(pana_conv_info_t));
|
||||
pana_info->pdus=se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "pana_pdus");
|
||||
pana_info->pdus = se_tree_create_non_persistent(
|
||||
EMEM_TREE_TYPE_RED_BLACK, "pana_pdus");
|
||||
|
||||
conversation_add_proto_data(conversation, proto_pana, pana_info);
|
||||
}
|
||||
if(!pinfo->fd->flags.visited){
|
||||
if(flags&PANA_FLAG_R){
|
||||
if (!pinfo->fd->flags.visited) {
|
||||
if (flags&PANA_FLAG_R) {
|
||||
/* This is a request */
|
||||
pana_trans=se_alloc(sizeof(pana_transaction_t));
|
||||
pana_trans->req_frame=pinfo->fd->num;
|
||||
pana_trans->rep_frame=0;
|
||||
pana_trans->req_time=pinfo->fd->abs_ts;
|
||||
pana_trans = se_alloc(sizeof(pana_transaction_t));
|
||||
pana_trans->req_frame = pinfo->fd->num;
|
||||
pana_trans->rep_frame = 0;
|
||||
pana_trans->req_time = pinfo->fd->abs_ts;
|
||||
se_tree_insert32(pana_info->pdus, seq_num, (void *)pana_trans);
|
||||
} else {
|
||||
pana_trans=se_tree_lookup32(pana_info->pdus, seq_num);
|
||||
if(pana_trans){
|
||||
pana_trans->rep_frame=pinfo->fd->num;
|
||||
pana_trans = se_tree_lookup32(pana_info->pdus, seq_num);
|
||||
if (pana_trans) {
|
||||
pana_trans->rep_frame = pinfo->fd->num;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
pana_trans=se_tree_lookup32(pana_info->pdus, seq_num);
|
||||
pana_trans = se_tree_lookup32(pana_info->pdus, seq_num);
|
||||
}
|
||||
if(!pana_trans){
|
||||
if (!pana_trans) {
|
||||
/* create a "fake" pana_trans structure */
|
||||
pana_trans=ep_alloc(sizeof(pana_transaction_t));
|
||||
pana_trans->req_frame=0;
|
||||
pana_trans->rep_frame=0;
|
||||
pana_trans->req_time=pinfo->fd->abs_ts;
|
||||
pana_trans = ep_alloc(sizeof(pana_transaction_t));
|
||||
pana_trans->req_frame = 0;
|
||||
pana_trans->rep_frame = 0;
|
||||
pana_trans->req_time = pinfo->fd->abs_ts;
|
||||
}
|
||||
|
||||
/* print state tracking in the tree */
|
||||
if(flags&PANA_FLAG_R){
|
||||
if (flags&PANA_FLAG_R) {
|
||||
/* This is a request */
|
||||
if(pana_trans->rep_frame){
|
||||
if (pana_trans->rep_frame) {
|
||||
proto_item *it;
|
||||
|
||||
it=proto_tree_add_uint(pana_tree, hf_pana_response_in, tvb, 0, 0, pana_trans->rep_frame);
|
||||
it = proto_tree_add_uint(pana_tree, hf_pana_response_in,
|
||||
tvb, 0, 0, pana_trans->rep_frame);
|
||||
PROTO_ITEM_SET_GENERATED(it);
|
||||
}
|
||||
} else {
|
||||
/* This is a reply */
|
||||
if(pana_trans->req_frame){
|
||||
if (pana_trans->req_frame) {
|
||||
proto_item *it;
|
||||
nstime_t ns;
|
||||
|
||||
it=proto_tree_add_uint(pana_tree, hf_pana_response_to, tvb, 0, 0, pana_trans->req_frame);
|
||||
it = proto_tree_add_uint(pana_tree, hf_pana_response_to,
|
||||
tvb, 0, 0, pana_trans->req_frame);
|
||||
PROTO_ITEM_SET_GENERATED(it);
|
||||
|
||||
nstime_delta(&ns, &pinfo->fd->abs_ts, &pana_trans->req_time);
|
||||
it=proto_tree_add_time(pana_tree, hf_pana_time, tvb, 0, 0, &ns);
|
||||
it = proto_tree_add_time(pana_tree, hf_pana_time, tvb, 0, 0, &ns);
|
||||
PROTO_ITEM_SET_GENERATED(it);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Then we just need to declare the hf fields we used
|
||||
Then we just need to declare the hf fields we used.
|
||||
|
||||
{ &hf_pana_response_in,
|
||||
{ "Response In", "pana.response_in",
|
||||
|
|
Loading…
Reference in New Issue