static int dissect_bfcp_attributes(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, int bfcp_payload_length) { proto_item *ti, *item; proto_tree *bfcp_attr_tree = NULL; gint attr_start_offset; gint length; guint8 attribute_type; gint read_attr = 0; guint8 first_byte, pad_len; while ((tvb_reported_length_remaining(tvb, offset) >= 2) && ((bfcp_payload_length - read_attr) >= 2)) { attr_start_offset = offset; first_byte = tvb_get_guint8(tvb, offset); /* Padding so continue to next attribute */ if (first_byte == 0){ read_attr++; continue; } ti = proto_tree_add_item(tree, hf_bfcp_attribute_types, tvb, offset, 1, ENC_BIG_ENDIAN); bfcp_attr_tree = proto_item_add_subtree(ti, ett_bfcp_attr); proto_tree_add_item(bfcp_attr_tree, hf_bfcp_attribute_types_m_bit, tvb, offset, 1, ENC_BIG_ENDIAN); attribute_type = (first_byte & 0xFE) >> 1; offset++; /* Length: This 8-bit field contains the length of the attribute in * octets, excluding any padding defined for specific attributes. The * length of attributes that are not grouped includes the Type, 'M' bit, * and Length fields. The Length in grouped attributes is the length of * the grouped attribute itself (including Type, 'M' bit, and Length * fields) plus the total length (including padding) of all the included * attributes. */ item = proto_tree_add_item(bfcp_attr_tree, hf_bfcp_attribute_length, tvb, offset, 1, ENC_BIG_ENDIAN); length = tvb_get_guint8(tvb, offset); offset++; pad_len = 0; /* Default to no padding*/ switch(attribute_type){ case 1: /* Beneficiary ID */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_beneficiary_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; break; case 2: /* FLOOR-ID */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_floor_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; break; case 3: /* FLOOR-REQUEST-ID */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_floor_request_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; break; case 4: /* PRIORITY */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_priority, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; break; case 5: /* REQUEST-STATUS */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_request_status, tvb, offset,1, ENC_BIG_ENDIAN); offset++; /* Queue Position */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_queue_pos, tvb, offset,1, ENC_BIG_ENDIAN); offset++; break; case 6: /* ERROR-CODE */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_error_code, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; if(length>3){ /* We have Error Specific Details */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_error_specific_details, tvb, offset, length-3, ENC_NA); } offset = offset + length-3; pad_len = length & 0x03; if(pad_len != 0){ pad_len = 4 - pad_len; proto_tree_add_item(bfcp_attr_tree, hf_bfcp_padding, tvb, offset, pad_len, ENC_NA); } offset = offset + pad_len; break; case 7: /* ERROR-INFO */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_error_info_text, tvb, offset, length-3, ENC_ASCII|ENC_NA); offset = offset + length-3; pad_len = length & 0x03; if(pad_len != 0){ pad_len = 4 - pad_len; proto_tree_add_item(bfcp_attr_tree, hf_bfcp_padding, tvb, offset, pad_len, ENC_NA); } offset = offset + pad_len; break; case 8: /* PARTICIPANT-PROVIDED-INFO */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_part_prov_info_text, tvb, offset, length-3, ENC_ASCII|ENC_NA); offset = offset + length-3; pad_len = length & 0x03; if(pad_len != 0){ pad_len = 4 - pad_len; proto_tree_add_item(bfcp_attr_tree, hf_bfcp_padding, tvb, offset, pad_len, ENC_NA); } offset = offset + pad_len; break; case 9: /* STATUS-INFO */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_status_info_text, tvb, offset, length-3, ENC_ASCII|ENC_NA); offset = offset + length-3; pad_len = length & 0x03; if(pad_len != 0){ pad_len = 4 - pad_len; proto_tree_add_item(bfcp_attr_tree, hf_bfcp_padding, tvb, offset, pad_len, ENC_NA); } offset = offset + pad_len; break; case 10: /* SUPPORTED-ATTRIBUTES */ while(offset < (attr_start_offset+length)){ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_supp_attr, tvb, offset, 1, ENC_BIG_ENDIAN); offset+=1; } pad_len = length & 0x03; if(pad_len != 0){ pad_len = 4 - pad_len; proto_tree_add_item(bfcp_attr_tree, hf_bfcp_padding, tvb, offset, pad_len, ENC_NA); } offset = offset + pad_len; break; case 11: /* SUPPORTED-PRIMITIVES */ while(offset < (attr_start_offset+length)){ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_supp_prim, tvb, offset, 1, ENC_BIG_ENDIAN); offset+=1; } pad_len = length & 0x03; if(pad_len != 0){ pad_len = 4 - pad_len; proto_tree_add_item(bfcp_attr_tree, hf_bfcp_padding, tvb, offset, pad_len, ENC_NA); } offset = offset + pad_len; break; case 12: /* USER-DISPLAY-NAME */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_user_disp_name, tvb, offset, length-3, ENC_ASCII|ENC_NA); offset = offset + length-3; pad_len = length & 0x03; if(pad_len != 0){ pad_len = 4 - pad_len; proto_tree_add_item(bfcp_attr_tree, hf_bfcp_padding, tvb, offset, pad_len, ENC_NA); } offset = offset + pad_len; break; case 13: /* USER-URI */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_user_uri, tvb, offset, length-3, ENC_ASCII|ENC_NA); offset = offset + length-3; pad_len = length & 0x03; if(pad_len != 0){ pad_len = 4 - pad_len; proto_tree_add_item(bfcp_attr_tree, hf_bfcp_padding, tvb, offset, pad_len, ENC_NA); } offset = offset + pad_len; break; case 14: /* BENEFICIARY-INFORMATION */ /* The BENEFICIARY-INFORMATION attribute is a grouped attribute that * consists of a header, which is referred to as BENEFICIARY- * INFORMATION-HEADER, followed by a sequence of attributes. */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_beneficiary_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; offset = dissect_bfcp_attributes(tvb, pinfo, bfcp_attr_tree, offset, length -4); break; case 15: /* FLOOR-REQUEST-INFORMATION */ /* The FLOOR-REQUEST-INFORMATION attribute is a grouped attribute that * consists of a header, which is referred to as FLOOR-REQUEST- * INFORMATION-HEADER, followed by a sequence of attributes. */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_floor_request_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; offset = dissect_bfcp_attributes(tvb, pinfo, bfcp_attr_tree, offset, length -4); break; case 16: /* REQUESTED-BY-INFORMATION */ /* The REQUESTED-BY-INFORMATION attribute is a grouped attribute that * consists of a header, which is referred to as FLOOR-REQUEST-STATUS- * -HEADER, followed by a sequence of attributes. */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_req_by_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; offset = dissect_bfcp_attributes(tvb, pinfo, bfcp_attr_tree, offset, length -4); break; case 17: /* FLOOR-REQUEST-STATUS */ /* The FLOOR-REQUEST-STATUS attribute is a grouped attribute that * consists of a header, which is referred to as OVERALL-REQUEST-STATUS- * -HEADER, followed by a sequence of attributes. */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_floor_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; offset = dissect_bfcp_attributes(tvb, pinfo, bfcp_attr_tree, offset, length -4); break; case 18: /* OVERALL-REQUEST-STATUS */ /* The OVERALL-REQUEST-STATUS attribute is a grouped attribute that * consists of a header, which is referred to as FLOOR-REQUEST- * INFORMATION-HEADER, followed by a sequence of attributes. */ proto_tree_add_item(bfcp_attr_tree, hf_bfcp_floor_request_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; offset = dissect_bfcp_attributes(tvb, pinfo, bfcp_attr_tree, offset, length -4); break; default: proto_tree_add_item(bfcp_attr_tree, hf_bfcp_payload, tvb, offset, length-2, ENC_NA); offset = offset + length - 2; break; } if ((length+pad_len) < (offset - attr_start_offset)){ expert_add_info_format(pinfo, item, &ei_bfcp_attribute_length_too_small, "Attribute length is too small (%d bytes)", length); break; } read_attr = read_attr + length; } return offset; }
/* Code to actually dissect BFCP packets */ static void dissect_bfcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) { int offset = 0; guint8 primitive; const gchar *str; gint bfcp_payload_length; proto_tree *bfcp_tree = NULL; primitive = tvb_get_guint8(tvb, 1); str = try_val_to_str(primitive, map_bfcp_primitive); /* Make entries in Protocol column and Info column on summary display*/ col_set_str(pinfo->cinfo, COL_PROTOCOL, "BFCP"); col_add_str(pinfo->cinfo, COL_INFO, str); if (tree) { proto_item *ti; ti = proto_tree_add_item(tree, proto_bfcp, tvb, 0, -1, ENC_NA); bfcp_tree = proto_item_add_subtree(ti, ett_bfcp); /* The following is the format of the common header. 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Ver |R|F| Res | Primitive | Payload Length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Conference ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Transaction ID | User ID | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | Fragment Offset (if F is set) | Fragment Length (if F is set) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ */ /* Add items to BFCP tree */ proto_tree_add_item(bfcp_tree, hf_bfcp_version, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(bfcp_tree, hf_bfcp_hdr_r_bit, tvb, offset, 1, ENC_BIG_ENDIAN); proto_tree_add_item(bfcp_tree, hf_bfcp_hdr_f_bit, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(bfcp_tree, hf_bfcp_primitive, tvb, offset, 1, ENC_BIG_ENDIAN); offset++; proto_tree_add_item(bfcp_tree, hf_bfcp_payload_length, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; proto_tree_add_item(bfcp_tree, hf_bfcp_conference_id, tvb, offset, 4, ENC_BIG_ENDIAN); offset+=4; proto_tree_add_item(bfcp_tree, hf_bfcp_transaction_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; proto_tree_add_item(bfcp_tree, hf_bfcp_user_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2; bfcp_payload_length = tvb_get_ntohs(tvb, BFCP_OFFSET_PAYLOAD_LENGTH) * 4; /*offset = */dissect_bfcp_attributes(tvb, pinfo, bfcp_tree, offset, bfcp_payload_length); } /* if(tree) */ }