static void dissect_ancp_port_up_dn_mgmt(tvbuff_t *tvb, proto_tree *ancp_tree, gint offset) { proto_item *sti = NULL; proto_tree *tlv_tree = NULL, *dsl_tree = NULL; guint8 tech_type; guint16 tlen, ttype, stlvtype, stlvlen; gint16 num_tlvs, num_stlvs; gint val; proto_tree_add_item(ancp_tree, hf_ancp_port, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(ancp_tree, hf_ancp_port_sess_num, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(ancp_tree, hf_ancp_evt_seq_num, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(ancp_tree, hf_ancp_label, tvb, offset, 8, ENC_BIG_ENDIAN); offset += 8; /* Start of the Extension Block */ proto_tree_add_item(ancp_tree, hf_ancp_reserved, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* * We have already displayed the message type in the common header dissect * need not display this again here - skip it */ offset += 1; /* Message type in Ext Blk */ proto_tree_add_item(ancp_tree, hf_ancp_tech_type, tvb, offset, 1, ENC_BIG_ENDIAN); tech_type = tvb_get_guint8(tvb, offset); offset += 1; proto_tree_add_item(ancp_tree, hf_ancp_blk_len, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; if (tech_type == TECH_TYPE_DSL) { proto_tree_add_item(ancp_tree, hf_ancp_num_ext_tlvs, tvb, offset, 2, ENC_BIG_ENDIAN); num_tlvs = tvb_get_ntohs(tvb, offset); offset += 2; sti = proto_tree_add_item(ancp_tree, hf_ancp_len, tvb, offset, 2, ENC_BIG_ENDIAN); proto_item_append_text(sti, " (Extension Block)"); offset += 2; /* Create a TLV sub tree */ tlv_tree = proto_item_add_subtree(sti, ett_ancp_len); for( ;num_tlvs; num_tlvs--) { proto_tree_add_item(tlv_tree, hf_ancp_ext_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN); ttype = tvb_get_ntohs(tvb, offset); offset += 2; sti = proto_tree_add_item(tlv_tree, hf_ancp_len, tvb, offset, 2, ENC_BIG_ENDIAN); tlen = tvb_get_ntohs(tvb, offset); offset += 2; /* * Extension Block is common for event message and port * management message, but the TLVs that can appear * are different */ switch (ttype) { case TLV_DSL_LINE_ATTRIBUTES: /* Create a DSL Attribute SubTree */ dsl_tree = proto_item_add_subtree(sti, ett_ancp_ext_tlv_type); num_stlvs = tlen / 8; /* TODO - better way? */ for ( ;num_stlvs; num_stlvs--) { proto_tree_add_item(dsl_tree, hf_ancp_dsl_line_stlv_type, tvb, offset, 2, ENC_BIG_ENDIAN); stlvtype = tvb_get_ntohs(tvb, offset); offset += 2; /* Skip sub-tlv-len display for now */ stlvlen = tvb_get_ntohs(tvb, offset); offset += 2; /* Sub TLV Length */ sti = proto_tree_add_item(dsl_tree, hf_ancp_dsl_line_stlv_value, tvb, offset, stlvlen, ENC_BIG_ENDIAN); val = tvb_get_ntohl(tvb, offset); offset += stlvlen; /* Except loop-encap, rest are 4B */ switch (stlvtype) { case TLV_DSL_LINE_STATE: proto_item_append_text(sti, " (%s)", val_to_str(val, dsl_line_state_names, "Unknown (0x%02x)")); break; case TLV_DSL_TYPE: proto_item_append_text(sti, " (%s)", val_to_str(val, dsl_line_type_names, "Unknown (0x%02x)")); break; default: /* Add Unit */ proto_item_append_text(sti, " %s", val_to_str(stlvtype, dsl_line_attr_units, "Unknown (0x%02x)")); break; } SKIPPADDING(offset, stlvlen); } break; case TLV_PING_OPAQUE_DATA: /* 2 32b values*/ proto_tree_add_item(tlv_tree, hf_ancp_oam_opaque, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tlv_tree, hf_ancp_oam_opaque, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case TLV_PING_PARAMS: /* Count (1B) Timeout (1B), 2B empty */ proto_tree_add_item(tlv_tree, hf_ancp_oam_loopb_cnt, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(tlv_tree, hf_ancp_oam_timeout, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Lets not bother about 2B until IETF WG figures out */ offset += 2; break; default: /* Assume TLV value is string - covers ALCID, OAM resp */ proto_tree_add_item(tlv_tree, hf_ancp_ext_tlv_value_str, tvb, offset, tlen, ENC_ASCII|ENC_NA); offset += tlen; SKIPPADDING(offset, tlen); break; } /* end switch {ttype} */ } /* end for {numtlvs} */ } /* end if {DSL} */ }
static gint dissect_ancp_tlv(tvbuff_t *tvb, proto_tree *tlv_tree, gint offset) { guint16 tlen, ttype; gint16 num_stlvs; proto_item *tti; proto_tree_add_item(tlv_tree, hf_ancp_ext_tlv_type, tvb, offset, 2, ENC_BIG_ENDIAN); ttype = tvb_get_ntohs(tvb, offset); offset += 2; tti = proto_tree_add_item(tlv_tree, hf_ancp_ext_tlv_len, tvb, offset, 2, ENC_BIG_ENDIAN); tlen = tvb_get_ntohs(tvb, offset); offset += 2; /* * Extension Block is common for event message and port * management message, but the TLVs that can appear * are different */ switch (ttype) { case TLV_DSL_LINE_ATTRIBUTES: { proto_tree *dsl_tree; guint16 stlvtype, stlvlen; gint val; /* Create a DSL Attribute SubTree */ dsl_tree = proto_item_add_subtree(tti, ett_ancp_ext_tlv_type); num_stlvs = tlen / 8; /* TODO - better way? */ for ( ;num_stlvs; num_stlvs--) { proto_tree_add_item(dsl_tree, hf_ancp_dsl_line_stlv_type, tvb, offset, 2, ENC_BIG_ENDIAN); stlvtype = tvb_get_ntohs(tvb, offset); offset += 2; proto_tree_add_item(dsl_tree, hf_ancp_dsl_line_stlv_len, tvb, offset, 2, ENC_BIG_ENDIAN); stlvlen = tvb_get_ntohs(tvb, offset); offset += 2; /* Sub TLV Length */ tti = proto_tree_add_item(dsl_tree, hf_ancp_dsl_line_stlv_value, tvb, offset, stlvlen, ENC_BIG_ENDIAN); val = tvb_get_ntohl(tvb, offset); offset += stlvlen; /* Except loop-encap, rest are 4B */ switch (stlvtype) { case TLV_DSL_LINE_STATE: proto_item_append_text(tti, " (%s)", val_to_str(val, dsl_line_state_names, "Unknown (0x%02x)")); break; case TLV_DSL_TYPE: proto_item_append_text(tti, " (%s)", val_to_str(val, dsl_line_type_names, "Unknown (0x%02x)")); break; default: /* Add Unit */ proto_item_append_text(tti, " %s", val_to_str(stlvtype, dsl_line_attr_units, "Unknown (0x%02x)")); break; } SKIPPADDING(offset, stlvlen); } break; } case TLV_PING_OPAQUE_DATA: /* 2 32b values*/ proto_tree_add_item(tlv_tree, hf_ancp_oam_opaque, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; proto_tree_add_item(tlv_tree, hf_ancp_oam_opaque, tvb, offset, 4, ENC_BIG_ENDIAN); offset += 4; break; case TLV_PING_PARAMS: /* Count (1B) Timeout (1B), 2B empty */ proto_tree_add_item(tlv_tree, hf_ancp_oam_loopb_cnt, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; proto_tree_add_item(tlv_tree, hf_ancp_oam_timeout, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1; /* Lets not bother about 2B until IETF WG figures out */ offset += 2; break; default: /* Assume TLV value is string - covers ALCID, OAM resp */ proto_tree_add_item(tlv_tree, hf_ancp_ext_tlv_value_str, tvb, offset, tlen, ENC_ASCII|ENC_NA); offset += tlen; SKIPPADDING(offset, tlen); break; } /* end switch {ttype} */ return offset; }