The attached patch for the DVB-CI dissector creates a circuit for each DVB-CI
session, using the session number as circuit id.

The DVB-CI session commands are:

- open_session_request(resource_id)
- session_opened(resource_id, newly assigned session number)
- payload transfer(session_number, payload data)
- close session(session_number)

For now, the circuit will store the resource id and make it available (as a
generated item) to subsequent packets that contain only the session number.
Doing this, the resource id (which is like a tcp/udp port) can be used for
filtering.

svn path=/trunk/; revision=41253
This commit is contained in:
Jeff Morriss 2012-03-01 02:50:16 +00:00
parent 767ec314a0
commit 7c55e4513a
2 changed files with 142 additions and 73 deletions

View File

@ -165,7 +165,8 @@ typedef enum {
CT_ISUP, /* ISDN User Part CIC */
CT_IAX2, /* IAX2 call id */
CT_H223, /* H.223 logical channel number */
CT_BICC /* BICC Circuit identifier */
CT_BICC, /* BICC Circuit identifier */
CT_DVBCI /* DVB-CI session number */
/* Could also have ATM VPI/VCI pairs */
} circuit_type;

View File

@ -37,6 +37,7 @@
#include <glib.h>
#include <epan/addr_resolv.h>
#include <epan/circuit.h>
#include <epan/packet.h>
#include <epan/reassemble.h>
#include <epan/prefs.h>
@ -800,6 +801,10 @@ static int hf_dvbci_spdu_tag = -1;
static int hf_dvbci_sess_status = -1;
static int hf_dvbci_sess_nb = -1;
static int hf_dvbci_close_sess_status = -1;
static int hf_dvbci_res_id_type = -1;
static int hf_dvbci_res_class = -1;
static int hf_dvbci_res_type = -1;
static int hf_dvbci_res_ver = -1;
static int hf_dvbci_apdu_tag = -1;
static int hf_dvbci_app_type = -1;
static int hf_dvbci_app_manf = -1;
@ -2143,13 +2148,34 @@ dissect_dvbci_text(const gchar *title, tvbuff_t *tvb, gint offset,
}
static void
dissect_dvbci_res_id(tvbuff_t *tvb, gint offset,
packet_info *pinfo, proto_tree *tree, guint32 res_id,
gboolean show_col_info)
static proto_item *
dissect_res_id(tvbuff_t *tvb, gint offset, packet_info *pinfo,
proto_tree *tree, guint32 res_id, gboolean show_col_info)
{
proto_item *ti = NULL;
proto_tree *res_tree = NULL;
gint tvb_data_len;
/* there's two possible inputs for this function
the resource id is either in a tvbuff_t (tvb!=NULL, res_id==0)
or in a guint32 (tvb==NULL, res_id!=0) */
if (tvb) {
/* resource id comes in via tvbuff */
if (res_id!=0)
return NULL;
res_id = tvb_get_ntohl(tvb, offset);
tvb_data_len = RES_ID_LEN;
}
else {
/* resource id comes in via guint32 */
if (res_id==0)
return NULL;
/* we'll call proto_tree_add_...( tvb==NULL, offset==0, length==0 )
this creates a filterable item without any reference to a tvb */
offset = 0;
tvb_data_len = 0;
}
if (show_col_info) {
col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "%s Version %d",
@ -2159,24 +2185,33 @@ dissect_dvbci_res_id(tvbuff_t *tvb, gint offset,
}
if (tree) {
ti = proto_tree_add_text(
tree, tvb, offset, RES_ID_LEN, "Resource ID: 0x%04x", res_id);
ti = proto_tree_add_text(tree, tvb, offset, tvb_data_len,
"Resource ID: 0x%04x", res_id);
res_tree = proto_item_add_subtree(ti, ett_dvbci_res);
proto_tree_add_text(res_tree, tvb, 0, 0, "%s",
/* parameter "value" == complete resource id,
RES_..._MASK will be applied by the hf definition */
proto_tree_add_uint_format(res_tree, hf_dvbci_res_id_type,
tvb, offset, tvb_data_len, res_id, "%s",
decode_numeric_bitfield(res_id, RES_ID_TYPE_MASK, 32,
"Resource ID Type: 0x%x"));
proto_tree_add_text(res_tree, tvb, 0, 0, "%s",
decode_enumerated_bitfield_shifted(res_id, RES_CLASS_MASK, 32,
dvbci_res_class, "Resource Class: %s"));
proto_tree_add_text(res_tree, tvb, 0, 0, "%s",
proto_tree_add_uint_format(res_tree, hf_dvbci_res_class,
tvb, offset, tvb_data_len, res_id, "%s (%s)",
decode_numeric_bitfield(res_id, RES_CLASS_MASK, 32,
"Resource Class: 0x%x"),
val_to_str_const(RES_CLASS(res_id), dvbci_res_class,
"Invalid Resource class"));
proto_tree_add_uint_format(res_tree, hf_dvbci_res_type,
tvb, offset, tvb_data_len, res_id, "%s",
decode_numeric_bitfield(res_id, RES_TYPE_MASK, 32,
"Resource Type: 0x%x"));
proto_tree_add_text(res_tree, tvb, 0, 0, "%s",
proto_tree_add_uint_format(res_tree, hf_dvbci_res_ver,
tvb, offset, tvb_data_len, res_id, "%s",
decode_numeric_bitfield(res_id, RES_VER_MASK, 32,
"Resource Version: 0x%x"));
}
return ti;
}
/* dissect the body of a resource manager apdu */
@ -2187,7 +2222,6 @@ dissect_dvbci_payload_rm(guint32 tag, gint len_field,
{
const gchar *tag_str;
proto_item *pi;
guint32 res_id;
if (tag==T_PROFILE) {
if (len_field % RES_ID_LEN) {
@ -2201,8 +2235,7 @@ dissect_dvbci_payload_rm(guint32 tag, gint len_field,
}
while (tvb_reported_length_remaining(tvb, offset) > 0) {
res_id = tvb_get_ntohl(tvb, offset);
dissect_dvbci_res_id(tvb, offset, pinfo, tree, res_id, FALSE);
dissect_res_id(tvb, offset, pinfo, tree, 0, FALSE);
offset += RES_ID_LEN;
}
}
@ -3583,11 +3616,14 @@ dissect_dvbci_spdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
proto_tree *sess_tree = NULL;
guint8 tag;
const gchar *tag_str;
gint offset;
circuit_t *circuit = NULL;
proto_item *pi;
gint offset;
guint32 len_field;
const spdu_info_t *si;
proto_item *res_id_it = NULL;
guint32 res_id;
guint16 ssnb = 0; /* session numbers start with 1, 0 is invalid */
guint8 sess_stat;
tvbuff_t *payload_tvb = NULL;
gint payload_len;
@ -3644,33 +3680,40 @@ dissect_dvbci_spdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
switch(tag)
{
case T_OPEN_SESSION_REQUEST:
res_id = tvb_get_ntohl(tvb, offset); /* get 32bit big-endian */
dissect_dvbci_res_id(tvb, offset, pinfo, sess_tree, res_id, TRUE);
res_id_it = dissect_res_id(tvb, offset, pinfo, sess_tree, 0, TRUE);
break;
case T_CREATE_SESSION:
res_id = tvb_get_ntohl(tvb, offset);
dissect_dvbci_res_id(tvb, offset, pinfo, sess_tree, res_id, TRUE);
res_id_it = dissect_res_id(tvb, offset, pinfo, sess_tree, 0, TRUE);
/* DVB-CI uses network byte order == big endian */
proto_tree_add_item(
sess_tree, hf_dvbci_sess_nb, tvb,
offset+4, 2, ENC_BIG_ENDIAN);
ssnb = tvb_get_ntohs(tvb, offset+RES_ID_LEN);
proto_tree_add_item(sess_tree, hf_dvbci_sess_nb,
tvb, offset+RES_ID_LEN, 2, ENC_BIG_ENDIAN);
break;
case T_OPEN_SESSION_RESPONSE:
case T_CREATE_SESSION_RESPONSE:
sess_stat = tvb_get_guint8(tvb, offset);
proto_tree_add_item(
sess_tree, hf_dvbci_sess_status, tvb, offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(sess_tree, hf_dvbci_sess_status,
tvb, offset, 1, ENC_BIG_ENDIAN);
res_id = tvb_get_ntohl(tvb, offset+1);
dissect_dvbci_res_id(tvb, offset+1, pinfo, sess_tree, res_id, TRUE);
res_id_it = dissect_res_id(tvb, offset+1, pinfo, sess_tree, 0, TRUE);
ssnb = tvb_get_ntohs(tvb, offset+1+RES_ID_LEN);
proto_tree_add_item(sess_tree, hf_dvbci_sess_nb, tvb,
offset+1+RES_ID_LEN, 2, ENC_BIG_ENDIAN);
if (sess_stat == SESS_OPENED)
col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
"Session opened");
else
if (sess_stat != SESS_OPENED) {
col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Error");
break;
}
col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Session opened");
circuit = circuit_new(CT_DVBCI, (guint32)ssnb, pinfo->fd->num);
if (circuit) {
/* we always add the resource id immediately after the circuit
was created */
circuit_add_proto_data(
circuit, proto_dvbci, GUINT_TO_POINTER(res_id));
}
break;
case T_CLOSE_SESSION_REQUEST:
ssnb = tvb_get_ntohs(tvb, offset);
proto_tree_add_item(
sess_tree, hf_dvbci_sess_nb, tvb,
offset, 2, ENC_BIG_ENDIAN);
@ -3680,17 +3723,17 @@ dissect_dvbci_spdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
proto_tree_add_item(
sess_tree, hf_dvbci_close_sess_status, tvb,
offset, 1, ENC_BIG_ENDIAN);
proto_tree_add_item(
sess_tree, hf_dvbci_sess_nb, tvb,
offset+1, 2, ENC_BIG_ENDIAN);
if (sess_stat == SESS_CLOSED) {
col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
"Session closed");
}
else
col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Error");
sess_stat==SESS_CLOSED ? "Session closed" : "Error");
ssnb = tvb_get_ntohs(tvb, offset+1);
proto_tree_add_item(sess_tree, hf_dvbci_sess_nb,
tvb, offset+1, 2, ENC_BIG_ENDIAN);
circuit = find_circuit(CT_DVBCI, (guint32)ssnb, pinfo->fd->num);
if (circuit)
close_circuit(circuit, pinfo->fd->num);
break;
case T_SESSION_NUMBER:
ssnb = tvb_get_ntohs(tvb, offset);
proto_tree_add_item(
sess_tree, hf_dvbci_sess_nb, tvb,
offset, 2, ENC_BIG_ENDIAN);
@ -3702,6 +3745,19 @@ dissect_dvbci_spdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
break;
}
if (ssnb && !circuit)
circuit = find_circuit(CT_DVBCI, (guint32)ssnb, pinfo->fd->num);
/* if the packet contains no resource id, we add the cached id from
the circuit so that each packet has a resource id that can be
used for filtering */
if (circuit && !res_id_it) {
/* when a circuit is found, it always contains a valid resource id */
res_id = GPOINTER_TO_UINT(circuit_get_proto_data(circuit, proto_dvbci));
res_id_it = dissect_res_id(NULL, 0, pinfo, sess_tree, res_id, TRUE);
PROTO_ITEM_SET_GENERATED(res_id_it);
}
if (payload_tvb) {
proto_item_set_len(ti, spdu_len-tvb_reported_length(payload_tvb));
dissect_dvbci_apdu(payload_tvb, pinfo, tree, direction);
@ -4379,6 +4435,18 @@ proto_register_dvbci(void)
{ &hf_dvbci_close_sess_status,
{ "Session Status", "dvb-ci.close_session_status", FT_UINT8,
BASE_HEX, VALS(dvbci_close_sess_status), 0, NULL, HFILL } },
{ &hf_dvbci_res_id_type,
{ "Resource ID Type", "dvb-ci.res.id_type", FT_UINT32,
BASE_HEX, NULL, RES_ID_TYPE_MASK, NULL, HFILL } },
{ &hf_dvbci_res_class,
{ "Resource Class", "dvb-ci.res.class", FT_UINT32,
BASE_HEX, NULL, RES_CLASS_MASK, NULL, HFILL } },
{ &hf_dvbci_res_type,
{ "Resource Type", "dvb-ci.res.type", FT_UINT32,
BASE_HEX, NULL, RES_TYPE_MASK, NULL, HFILL } },
{ &hf_dvbci_res_ver,
{ "Resource Version", "dvb-ci.res.version", FT_UINT32,
BASE_HEX, NULL, RES_VER_MASK, NULL, HFILL } },
{ &hf_dvbci_apdu_tag,
{ "APDU Tag", "dvb-ci.apdu_tag", FT_UINT24, BASE_HEX,
VALS(dvbci_apdu_tag), 0, NULL, HFILL } },