📄 plugins-wimax-mac_hd_generic_decoder.c
字号:
guint mac_ht, mac_ec, mac_esf, mac_ci, mac_eks, mac_len, mac_cid, cid;
guint ffb_grant_mgmt_subheader, packing_subheader, fragment_subheader;
guint mesh_subheader;
guint packing_length;
guint32 mac_crc, calculated_crc;
proto_item *parent_item = NULL;
proto_item *generic_item = NULL;
proto_tree *generic_tree = NULL;
proto_item *child_item = NULL;
proto_tree *child_tree = NULL;
tvbuff_t *payload_tvb;
tvbuff_t *data_pdu_tvb;
fragment_data *payload_frag;
gboolean first_arq_fb_payload = TRUE;
dissector_handle_t mac_payload_handle;
proto_mac_header_generic_decoder = proto_wimax;
if (tree)
{ /* we are being asked for details */
#ifdef DEBUG
/* update the info column */
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "GMH");
}
#endif
/* Get the frame length */
tvb_len = tvb_reported_length(tvb);
if (tvb_len < WIMAX_MAC_HEADER_SIZE)
{ /* display the error message */
generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, tvb_len, "Error: the size of Generic MAC Header tvb is too small! (%u bytes)", tvb_len);
/* add subtree */
generic_tree = proto_item_add_subtree(generic_item, ett_mac_header_generic_decoder);
/* display the Generic MAC Header in Hex */
proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, tvb, offset, tvb_len, FALSE);
return;
}
/* get the parent */
parent_item = proto_tree_get_parent(tree);
/* add the MAC header info */
proto_item_append_text(parent_item, " - Generic MAC Header");
/* display MAC header message */
generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, WIMAX_MAC_HEADER_SIZE, "Generic MAC Header (%u bytes)", WIMAX_MAC_HEADER_SIZE);
/* add MAC header subtree */
generic_tree = proto_item_add_subtree(generic_item, ett_mac_header_generic_decoder);
/* Decode and display the MAC header */
/* Get the first byte */
ubyte = tvb_get_guint8(tvb, offset);
/* get the Header Type (HT) */
mac_ht = ((ubyte & WIMAX_MAC_HEADER_GENERIC_HT_MASK)?1:0);
/* get the Encryption Control (EC) */
mac_ec = ((ubyte & WIMAX_MAC_HEADER_GENERIC_EC_MASK)?1:0);
/* get the sub types */
ffb_grant_mgmt_subheader = ((ubyte & GENERIC_SUB_TYPE_0)?1:0);
packing_subheader = ((ubyte & GENERIC_SUB_TYPE_1)?1:0);
fragment_subheader = ((ubyte & GENERIC_SUB_TYPE_2)?1:0);
extended_type = ((ubyte & GENERIC_SUB_TYPE_3)?1:0);
arq_fb_payload = ((ubyte & GENERIC_SUB_TYPE_4)?1:0);
mesh_subheader = ((ubyte & GENERIC_SUB_TYPE_5)?1:0);
/* Get the 2nd byte */
ubyte = tvb_get_guint8(tvb, (offset+1));
/* get the Extended subheader field (ESF) */
mac_esf = ((ubyte & WIMAX_MAC_HEADER_GENERIC_ESF_MASK)?1:0);
/* get the CRC indicator (CI) */
mac_ci = ((ubyte & WIMAX_MAC_HEADER_GENERIC_CI_MASK)?1:0);
/* get the Encryption key sequence (EKS) */
mac_eks = ((ubyte & WIMAX_MAC_HEADER_GENERIC_EKS_MASK)>>4);
/* get the MAC length */
mac_len = (tvb_get_ntohs(tvb, (offset+1)) & WIMAX_MAC_HEADER_GENERIC_LEN);
/* get the CID */
mac_cid = tvb_get_ntohs(tvb, (offset+3));
/* display the Header Type (HT) */
proto_tree_add_item(generic_tree, hf_mac_header_generic_ht, tvb, offset, 3, FALSE);
/* display the Encryption Control (EC) */
proto_tree_add_item(generic_tree, hf_mac_header_generic_ec, tvb, offset, 3, FALSE);
/* display the sub-types (Type) */
proto_tree_add_item(generic_tree, hf_mac_header_generic_type_5, tvb, offset, 3, FALSE);
proto_tree_add_item(generic_tree, hf_mac_header_generic_type_4, tvb, offset, 3, FALSE);
proto_tree_add_item(generic_tree, hf_mac_header_generic_type_3, tvb, offset, 3, FALSE);
proto_tree_add_item(generic_tree, hf_mac_header_generic_type_2, tvb, offset, 3, FALSE);
proto_tree_add_item(generic_tree, hf_mac_header_generic_type_1, tvb, offset, 3, FALSE);
proto_tree_add_item(generic_tree, hf_mac_header_generic_type_0, tvb, offset, 3, FALSE);
/* display the Extended sub-header Field (ESF) */
proto_tree_add_item(generic_tree, hf_mac_header_generic_esf, tvb, offset, 3, FALSE);
/* display the CRC Indicator (CI) */
proto_tree_add_item(generic_tree, hf_mac_header_generic_ci, tvb, offset, 3, FALSE);
/* display the Encryption Key Sequence (EKS) */
proto_tree_add_item(generic_tree, hf_mac_header_generic_eks, tvb, offset, 3, FALSE);
/* display the reserved field */
proto_tree_add_item(generic_tree, hf_mac_header_generic_rsv, tvb, offset, 3, FALSE);
/* display the length */
proto_tree_add_item(generic_tree, hf_mac_header_generic_len, tvb, offset, 3, FALSE);
/* Decode and display the CID */
proto_tree_add_item(generic_tree, hf_mac_header_generic_cid, tvb, (offset+3), 2, FALSE);
/* Decode and display the HCS */
proto_tree_add_item(generic_tree, hf_mac_header_generic_hcs, tvb, (offset+5), 1, FALSE);
/* get the frame length without MAC header */
length = mac_len - WIMAX_MAC_HEADER_SIZE;
#ifdef DEBUG
proto_item_append_text(parent_item, "tvb length=%u, mac length=%u, frame length=%u,", tvb_len, mac_len, length);
#endif
/* set the offset for the frame */
offset += WIMAX_MAC_HEADER_SIZE;
/* the processing of the subheaders is order sensitive */
/* do not change the order */
if (mac_ec)
{
if (mac_ci)
{
if (length >= (gint)sizeof(mac_crc))
{
length -= sizeof(mac_crc);
}
}
generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Encrypted PDU (%u bytes)", length);
/* add payload subtree */
generic_tree = proto_item_add_subtree(generic_item, ett_mac_data_pdu_decoder);
proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, tvb, offset, length, FALSE);
goto check_crc;
}
/* if Extended subheader is present */
if (mac_esf)
{ /* add the Extended subheader info */
proto_item_append_text(parent_item, ", Extended Subheader(s)");
ret_length = extended_subheader_decoder(tvb_new_subset(tvb, offset, length, length), pinfo, tree);
/* update the length and offset */
length -= ret_length;
offset += ret_length;
}
/* if Mesh subheader is present */
if (mesh_subheader)
{ /* update the info column */
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Mesh subhdr");
}
/* add the Mesh subheader info */
proto_item_append_text(parent_item, ", Mesh Subheader");
/* display Mesh subheader type */
generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Mesh subheader (2 bytes)");
/* add Mesh subheader subtree */
generic_tree = proto_item_add_subtree(generic_item, ett_mac_mesh_subheader_decoder);
/* decode and display the Mesh subheader */
proto_tree_add_item(generic_tree, hf_mac_header_generic_mesh_subheader, tvb, offset, 2, FALSE);
/* update the length and offset */
length -= 2;
offset += 2;
}
/* if Fast-feedback allocation (DL) subheader or Grant management (UL) subheader is present */
if (ffb_grant_mgmt_subheader)
{ /* check if it is downlink packet */
if (is_down_link(&(pinfo->src)))
{ /* Fast-feedback allocation (DL) subheader is present */
/* update the info column */
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Fast-fb subhdr");
}
/* add the Fast-feedback subheader info */
proto_item_append_text(parent_item, ", Fast-feedback Subheader");
/* display Fast-feedback allocation subheader type */
generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Fast-feedback allocation (DL) subheader (%u bytes)", length);
/* add Fast-feedback allocation subheader subtree */
generic_tree = proto_item_add_subtree(generic_item, ett_mac_fast_fb_subheader_decoder);
proto_tree_add_item(generic_tree, hf_mac_header_generic_fast_fb_subhd_alloc_offset, tvb, offset, 1, FALSE);
proto_tree_add_item(generic_tree, hf_mac_header_generic_fast_fb_subhd_fb_type, tvb, offset, 1, FALSE);
/* update the length and offset */
length -= 1;
offset += 1;
}
else /* Grant management (UL) subheader is present */
{ /* update the info column */
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Grant mgmt subhdr");
}
/* add the Grant management subheader info */
proto_item_append_text(parent_item, ", Grant Management Subheader");
/* display Grant management subheader type */
generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, 2, "Grant management (UL) subheader (2 bytes)");
/* add Grant management subheader subtree */
generic_tree = proto_item_add_subtree(generic_item, ett_mac_grant_mgmt_subheader_decoder);
scheduling_service_type = get_service_type();
switch (scheduling_service_type)
{
case SCHEDULE_SERVICE_TYPE_UGS:
proto_item_append_text(generic_item, ": It looks like UGS is the correct Scheduling Service Type");
break;
case SCHEDULE_SERVICE_TYPE_EXT_RTPS:
proto_item_append_text(generic_item, ": It looks like Extended rtPS is the correct Scheduling Service Type");
break;
case -1:
proto_item_append_text(generic_item, ": Cannot determine the correct Scheduling Service Type");
break;
default:
proto_item_append_text(generic_item, ": It looks like Piggyback Request is the correct Scheduling Service Type");
break;
}
/* Create tree for Scheduling Service Type (UGS) */
child_item = proto_tree_add_item(generic_tree, hf_mac_header_generic_grant_mgmt_ugs_tree, tvb, offset, 2, FALSE);
child_tree = proto_item_add_subtree(child_item, ett_mac_grant_mgmt_subheader_decoder);
proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_si, tvb, offset, 2, FALSE);
proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_pm, tvb, offset, 2, FALSE);
proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_fli, tvb, offset, 2, FALSE);
proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_fl, tvb, offset, 2, FALSE);
proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ugs_rsv, tvb, offset, 2, FALSE);
/* Create tree for Scheduling Service Type (Extended RTPS) */
child_item = proto_tree_add_item(generic_tree, hf_mac_header_generic_grant_mgmt_ext_rtps_tree, tvb, offset, 2, FALSE);
child_tree = proto_item_add_subtree(child_item, ett_mac_grant_mgmt_subheader_decoder);
proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ext_pbr, tvb, offset, 2, FALSE);
proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ext_fli, tvb, offset, 2, FALSE);
proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_ext_fl, tvb, offset, 2, FALSE);
/* Create tree for Scheduling Service Type (Piggyback Request) */
child_item = proto_tree_add_item(generic_tree, hf_mac_header_generic_grant_mgmt_ext_pbr_tree, tvb, offset, 2, FALSE);
child_tree = proto_item_add_subtree(child_item, ett_mac_grant_mgmt_subheader_decoder);
proto_tree_add_item(child_tree, hf_mac_header_generic_grant_mgmt_subhd_pbr, tvb, offset, 2, FALSE);
/* update the length and offset */
length -= 2;
offset += 2;
}
}
/* if Fragmentation subheader is present */
if (fragment_subheader)
{ /* update the info column */
if (check_col(pinfo->cinfo, COL_INFO))
{
col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "Frag subhdr");
}
/* add the Fragmentation subheader info */
proto_item_append_text(parent_item, ", Frag Subheader");
/* display Fragmentation subheader type */
generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, ((arq_enabled|extended_type)?2:1), "Fragmentation subheader (%u bytes)", ((arq_enabled|extended_type)?2:1));
/* add Fragmentation subheader subtree */
generic_tree = proto_item_add_subtree(generic_item, ett_mac_frag_subheader_decoder);
/* Get the fragment type */
frag_type = (tvb_get_guint8(tvb, offset) & FRAGMENT_TYPE_MASK) >> 6;
if (arq_fb_payload)
{ /* get the sequence number */
seq_number = (tvb_get_ntohs(tvb, offset) & SEQ_NUMBER_MASK_11) >> 3;
/* decode and display the header */
proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fc_ext, tvb, offset, 2, FALSE);
proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_bsn, tvb, offset, 2, FALSE);
proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_rsv_ext, tvb, offset, 2, FALSE);
/* update the length and offset */
length -= 2;
offset += 2;
}
else
{
if (extended_type)
{ /* get the sequence number */
seq_number = (tvb_get_ntohs(tvb, offset) & SEQ_NUMBER_MASK_11) >> 3;
/* decode and display the header */
proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fc_ext, tvb, offset, 2, FALSE);
proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fsn_ext, tvb, offset, 2, FALSE);
proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_rsv_ext, tvb, offset, 2, FALSE);
/* update the length and offset */
length -= 2;
offset += 2;
}
else
{ /* get the sequence number */
seq_number = (tvb_get_guint8(tvb, offset) & SEQ_NUMBER_MASK) >> 3;
/* decode and display the header */
proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fc, tvb, offset, 1, FALSE);
proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_fsn, tvb, offset, 1, FALSE);
proto_tree_add_item(generic_tree, hf_mac_header_generic_frag_subhd_rsv, tvb, offset, 1, FALSE);
/* update the length and offset */
length -= 1;
offset += 1;
}
}
frag_len = length;
}
else /* ??? default fragment type: no fragment */
{
frag_type = NO_FRAG;
}
/* Decode the MAC payload if there is any */
if (mac_ci)
{
if (length < (gint)sizeof(mac_crc))
{ /* display error message */
proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, length, "Error - the frame is too short (%u bytes)", length);
return;
}
length -= sizeof(mac_crc);
}
while (length > 0)
{
frag_len = length; /* Can be changed by Packing subhdr */
if (packing_subheader)
{
packing_length = decode_packing_subheader(tvb, pinfo, tree, length, offset, parent_item);
length -= packing_length;
offset += packing_length;
generic_item = proto_tree_add_protocol_format(tree, proto_mac_header_generic_decoder, tvb, offset, frag_len, "Data transport PDU (%u bytes)", frag_len);
/* add payload subtree */
generic_tree = proto_item_add_subtree(generic_item, ett_mac_data_pdu_decoder);
proto_tree_add_item(generic_tree, hf_mac_header_generic_value_bytes, tvb, offset, frag_len, FALSE);
}
/* defragment first if it is fragmented */
if (frag_type == NO_FRAG)
{ /* not fragmented payload */
payload_tvb = tvb_new_subset(tvb, offset, length, length);
payload_length = length;
new_payload_len = length;
}
else /* fragmented payload */
{ /* add the frag */
/* Make sure cid will not match a previous packet with different data */
for (i = 0; i < MAX_CID; i++)
{
if (cid_list[i] == mac_cid)
{
cid_base = i * (0xFFFFFFFF / MAX_CID);
break;
}
if (cid_list[i] == 0)
{
cid_list[i] = mac_cid;
cid_base = i * (0xFFFFFFFF / MAX_CID);
break;
}
}
cid_index = i;
while (pinfo->fd->num > cid_adj_array_size)
{
cid_adj_array_size += 1024;
cid_adj_array = g_realloc(cid_adj_array, sizeof(guint) * cid_adj_array_size);
frag_num_array = g_realloc(frag_num_array, sizeof(guint8) * cid_adj_array_size);
/* Clear the added memory */
memset(&cid_adj_array[cid_adj_array_size - 1024], 0, sizeof(guint) * 1024);
}
if (first_gmh)
{
/* New cid_adjust for each packet with fragment(s) */
cid_adjust[cid_index] += cid_vernier[cid_index];
/* cid_vernier must always be 0 at start of packet. */
cid_vernier[cid_index] = 0;
}
/* Create artificial sequence numbers. */
frag_number[cid_index]++;
if (frag_type == FIRST_FRAG)
{
frag_number[cid_index] = 0;
}
if (cid_adj_array[pinfo->fd->num])
{
/* We apparently just clicked on the packet again. */
cid_adjust[cid_index] = cid_adj_array[pinfo->fd->num];
/* Set the frag_number at start of packet. */
if (first_gmh)
{
frag_number[cid_index] = frag_num_array[pinfo->fd->num];
}
} else {
/* Save for next time we click on this packet. */
cid_adj_array[pinfo->fd->num] = cid_adjust[cid_index];
if (first_gmh)
{
frag_num_array[pinfo->fd->num] = frag_number[cid_index];
}
}
/* Reset in case we stay in this while() loop to finish the packet. */
first_gmh = FALSE;
cid = cid_base + cid_adjust[cid_index] + cid_vernier[cid_index];
/* Save address pointers. */
save_src = pinfo->src;
save_dst = pinfo->dst;
/* Use dl_src and dl_dst in defrag. */
pinfo->src = pinfo->dl_src;
pinfo->dst = pinfo->dl_dst;
payload_frag = fragment_add_seq(tvb, offset, pinfo, cid, payload_frag_table, frag_number[cid_index], frag_len, ((frag_type==LAST_FRAG)?0:1));
/* Restore address pointers. */
pinfo->src = save_src;
pinfo->dst = save_dst;
if (frag_type == LAST_FRAG)
{
/* Make sure fragment_add_seq() sees next one as a new frame. */
cid_vernier[cid_index]++;
}
/* Don't show reassem packet until last frag. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -