コード例 #1
0
ファイル: packet-pana.c プロジェクト: DHODoS/wireshark
/*
 * Function for the PANA PDU dissector.
 */
static void
dissect_pana_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

        proto_tree        *pana_tree = NULL;
        guint16            flags;
        guint16            msg_type;
        guint32            msg_length;
        guint32            avp_length;
        guint32            seq_num;
        conversation_t     *conversation;
        pana_conv_info_t   *pana_info;
        pana_transaction_t *pana_trans;
        int offset = 0;

        col_set_str(pinfo->cinfo, COL_PROTOCOL, "PANA");
        col_clear(pinfo->cinfo,   COL_INFO);

        /* Get message length, type and flags */
        msg_length = tvb_get_ntohs(tvb, 2);
        flags      = tvb_get_ntohs(tvb, 4);
        msg_type   = tvb_get_ntohs(tvb, 6);
        seq_num    = tvb_get_ntohl(tvb, 12);
        avp_length = msg_length - 16;

        col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s-%s",
                     val_to_str(msg_type, msg_type_names, "Unknown (%d)"),
                     val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)"));

        /* Make the protocol tree */
        if (tree) {
                proto_item *ti;
                ti = proto_tree_add_item(tree, proto_pana, tvb, 0, -1, ENC_NA);
                pana_tree = proto_item_add_subtree(ti, ett_pana);
        }


        /*
         * We need to track some state for this protocol on a per conversation
         * basis so we can do neat things like request/response tracking
         */
        conversation = find_or_create_conversation(pinfo);

        /*
         * Do we already have a state structure for this conv
         */
        pana_info = (pana_conv_info_t *)conversation_get_proto_data(conversation, proto_pana);
        if (!pana_info) {
                /* No.  Attach that information to the conversation, and add
                 * it to the list of information structures.
                 */
                pana_info = wmem_new(wmem_file_scope(), pana_conv_info_t);
                pana_info->pdus=wmem_map_new(wmem_file_scope(), g_direct_hash, g_direct_equal);

                conversation_add_proto_data(conversation, proto_pana, pana_info);
        }

        if(!pinfo->fd->flags.visited){
                if(flags&PANA_FLAG_R){
                        /* This is a request */
                        pana_trans=wmem_new(wmem_file_scope(), pana_transaction_t);
                        pana_trans->req_frame=pinfo->num;
                        pana_trans->rep_frame=0;
                        pana_trans->req_time=pinfo->abs_ts;
                        wmem_map_insert(pana_info->pdus, GUINT_TO_POINTER(seq_num), (void *)pana_trans);
                } else {
                        pana_trans=(pana_transaction_t *)wmem_map_lookup(pana_info->pdus, GUINT_TO_POINTER(seq_num));
                        if(pana_trans){
                                pana_trans->rep_frame=pinfo->num;
                        }
                }
        } else {
                pana_trans=(pana_transaction_t *)wmem_map_lookup(pana_info->pdus, GUINT_TO_POINTER(seq_num));
        }

        if(!pana_trans){
                /* create a "fake" pana_trans structure */
                pana_trans=wmem_new(wmem_packet_scope(), pana_transaction_t);
                pana_trans->req_frame=0;
                pana_trans->rep_frame=0;
                pana_trans->req_time=pinfo->abs_ts;
        }

        /* print state tracking in the tree */
        if(flags&PANA_FLAG_R){
                /* This is a request */
                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);
                        PROTO_ITEM_SET_GENERATED(it);
                }
        } else {
                /* This is a reply */
                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);
                        PROTO_ITEM_SET_GENERATED(it);

                        nstime_delta(&ns, &pinfo->abs_ts, &pana_trans->req_time);
                        it=proto_tree_add_time(pana_tree, hf_pana_response_time, tvb, 0, 0, &ns);
                        PROTO_ITEM_SET_GENERATED(it);
                }
        }

        /* Reserved field */
        proto_tree_add_item(pana_tree, hf_pana_reserved_type, tvb, offset, 2, ENC_NA);
        offset += 2;

        /* Length */
        proto_tree_add_item(pana_tree, hf_pana_length_type, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;

        /* Flags */
        dissect_pana_flags(pana_tree, tvb, offset, flags);
        offset += 2;

        /* Message Type */
        proto_tree_add_uint_format_value(pana_tree, hf_pana_msg_type, tvb,
                                         offset, 2, msg_type, "%s-%s (%d)",
                                         val_to_str(msg_type, msg_type_names, "Unknown (%d)"),
                                         val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)"),
                                         msg_type);
        offset += 2;

        /* Session ID */
        proto_tree_add_item(pana_tree, hf_pana_session_id, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;

        /* Sequence Number */
        proto_tree_add_item(pana_tree, hf_pana_seqnumber, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;

        /* AVPs */
        if(avp_length != 0){
                tvbuff_t   *avp_tvb;
                proto_tree *avp_tree;
                avp_tvb  = tvb_new_subset_length(tvb, offset, avp_length);
                avp_tree = proto_tree_add_subtree(pana_tree, tvb, offset, avp_length, ett_pana_avp, NULL, "Attribute Value Pairs");

                dissect_avps(avp_tvb, pinfo, avp_tree);
        }

}
コード例 #2
0
/*
 * Function for the PANA PDU dissector.
 */
static void
dissect_pana_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

       proto_tree *pana_tree=NULL;
       proto_tree *avp_tree=NULL;
       proto_item *ti=NULL;
       proto_item *avp_item=NULL;
       tvbuff_t *avp_tvb;
       guint16 flags = 0;
       guint16 msg_type;
       gint16 msg_length;
       gint16 avp_length;
       guint32 session_id;
       guint32 seq_num;
       conversation_t *conversation;
       pana_conv_info_t *pana_info;
       pana_transaction_t *pana_trans;
       int offset = 0;


       /* Get message length, type and flags */
       msg_length = tvb_get_ntohs(tvb, 2);
       flags = tvb_get_ntohs(tvb, 4);
       msg_type = tvb_get_ntohs(tvb, 6);
       session_id = tvb_get_ntohl(tvb, 8);
       seq_num = tvb_get_ntohl(tvb, 12);
       avp_length = msg_length-16;

       /* Make entries in Protocol column and Info column on summary display */
       col_set_str(pinfo->cinfo, COL_PROTOCOL, "PANA");

       if (check_col(pinfo->cinfo, COL_INFO)) {
               col_clear(pinfo->cinfo, COL_INFO);
               col_add_fstr(pinfo->cinfo, COL_INFO, "Type %s-%s",
			    val_to_str(msg_type, msg_type_names, "Unknown (%d)"),
			    val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)"));
       }

       /* Make the protocol tree */
       if (tree) {
               ti = proto_tree_add_item(tree, proto_pana, tvb, 0, -1, FALSE);
               pana_tree = proto_item_add_subtree(ti, ett_pana);
       }


       /*
        * We need to track some state for this protocol on a per conversation
        * basis so we can do neat things like request/response tracking
        */
       /*
        * Do we have a conversation for this connection?
        */
       conversation = find_conversation(pinfo->fd->num,
                                   &pinfo->src, &pinfo->dst,
                                   pinfo->ptype,
                                   pinfo->srcport, pinfo->destport, 0);
       if (conversation == NULL) {
             /* We don't yet have a conversation, so create one. */
             conversation = conversation_new(pinfo->fd->num,
                                   &pinfo->src, &pinfo->dst,
    	                    	   pinfo->ptype,
                                   pinfo->srcport, pinfo->destport, 0);
       }
       /*
        * Do we already have a state structure for this conv
        */
       pana_info = conversation_get_proto_data(conversation, proto_pana);
       if (!pana_info) {
               /* 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");

               conversation_add_proto_data(conversation, proto_pana, pana_info);
       }
       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;
                      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;
                      }
               }
       } else {
               pana_trans=se_tree_lookup32(pana_info->pdus, seq_num);
       }
       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;
       }


       /* print state tracking in the tree */
       if(flags&PANA_FLAG_R){
               /* This is a request */
               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);
                       PROTO_ITEM_SET_GENERATED(it);
               }
       } else {
               /* This is a reply */
               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);
                       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);
                       PROTO_ITEM_SET_GENERATED(it);
               }
       }



       /* Reserved field */
       proto_tree_add_item(pana_tree, hf_pana_reserved_type, tvb, offset, 2, FALSE);
       offset += 2;

       /* Length */
       proto_tree_add_item(pana_tree, hf_pana_length_type, tvb, offset, 2, FALSE);
       offset += 2;

       /* Flags */
       dissect_pana_flags(pana_tree, tvb, offset, flags);
       offset += 2;

       /* Message Type */
       proto_tree_add_uint_format_value(pana_tree, hf_pana_msg_type, tvb,
                           offset, 2, msg_type, "%s-%s (%d)",
                           val_to_str(msg_type, msg_type_names, "Unknown (%d)"),
			   val_to_str(flags & PANA_FLAG_R, msg_subtype_names, "Unknown (%d)"),
			   msg_type);
       offset += 2;

       /* Session ID */
       proto_tree_add_item(pana_tree, hf_pana_session_id, tvb, offset, 4, FALSE);
       offset += 4;

       /* Sequence Number */
       proto_tree_add_item(pana_tree, hf_pana_seqnumber, tvb, offset, 4, FALSE);
       offset += 4;

       /* AVPs */
       if(avp_length>0){
               avp_tvb = tvb_new_subset(tvb, offset, avp_length, avp_length);
               avp_item = proto_tree_add_text(pana_tree, tvb, offset, avp_length, "Attribute Value Pairs");
               avp_tree = proto_item_add_subtree(avp_item, ett_pana_avp);

               if (avp_tree != NULL) {
                       dissect_avps(avp_tvb, pinfo, avp_tree);
               }
        }
}
コード例 #3
0
ファイル: packet-pana.c プロジェクト: DHODoS/wireshark
/*
 * Function for AVP dissector.
 */
static void
dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree)
{

        gint    offset;
        guint16 avp_code;
        guint16 avp_flags;
        guint32 avp_length;
        guint16 avp_type;
        guint32 vendor_id;
        guint32 avp_hdr_length;
        guint32 avp_data_length, result_code;
        guint32 padding;

        gint32  buffer_length;

        tvbuff_t   *group_tvb;
        tvbuff_t   *eap_tvb;
        tvbuff_t   *encap_tvb;
        proto_tree *single_avp_tree;
        proto_tree *avp_eap_tree;
        proto_tree *avp_encap_tree;

        offset = 0;
        buffer_length = tvb_reported_length(tvb);

        /* Go through all AVPs */
        while (buffer_length > 0) {
                avp_code        = tvb_get_ntohs(tvb, offset);
                avp_flags       = tvb_get_ntohs(tvb, offset + 2);
                avp_data_length = tvb_get_ntohs(tvb, offset + 4);

                /* Check AVP flags for vendor specific AVP */
                if (avp_flags & PANA_AVP_FLAG_V) {
                        vendor_id      = tvb_get_ntohl(tvb, 8);
                        avp_hdr_length = 12;
                } else {
                        vendor_id = 0;
                        avp_hdr_length = 8;
                }

                avp_length = avp_hdr_length + avp_data_length;

                /* Check AVP type */
                avp_type = pana_avp_get_type(avp_code, vendor_id);


                /* Check padding */
                padding = (4 - (avp_length % 4)) % 4;

                single_avp_tree = proto_tree_add_subtree_format(avp_tree, tvb, offset, avp_length + padding,
                                                                ett_pana_avp_info, NULL, "%s (%s) length: %d bytes (%d padded bytes)",
                                                                val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
                                                                val_to_str(avp_type, avp_type_names, "Unknown (%d)"),
                                                                avp_length,
                                                                avp_length + padding);

                /* AVP Code */
                proto_tree_add_uint_format_value(single_avp_tree, hf_pana_avp_code, tvb,
                                                 offset, 2, avp_code, "%s (%u)",
                                                 val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
                                                 avp_code);
                offset += 2;

                /* AVP Flags */
                dissect_pana_avp_flags(single_avp_tree, tvb, offset, avp_flags);
                offset += 2;

                /* AVP Length */
                proto_tree_add_item(single_avp_tree, hf_pana_avp_data_length, tvb, offset, 2, ENC_BIG_ENDIAN);
                offset += 2;

                /* Reserved */
                proto_tree_add_item(single_avp_tree, hf_pana_avp_reserved, tvb, offset, 2, ENC_NA);
                offset += 2;

                if (avp_flags & PANA_AVP_FLAG_V) {
                        /* Vendor ID */
                        proto_tree_add_item(single_avp_tree, hf_pana_avp_vendorid, tvb, offset, 4, ENC_BIG_ENDIAN);
                        offset += 4;
                }
                if (! (avp_flags & PANA_AVP_FLAG_V)) {
                        /* AVP Value */
                        switch(avp_type) {
                                case PANA_GROUPED: {
                                        proto_tree *avp_group_tree;
                                        avp_group_tree = proto_tree_add_subtree(single_avp_tree,
                                                                                tvb, offset, avp_data_length,
                                                                                ett_pana_avp, NULL, "Grouped AVP");
                                        group_tvb = tvb_new_subset(tvb, offset,
                                                                   MIN(avp_data_length, tvb_reported_length(tvb)-offset),
                                                                   avp_data_length);
                                        dissect_avps(group_tvb, pinfo, avp_group_tree);
                                        break;
                                }
                                case PANA_UTF8STRING: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_string, tvb,
                                                                     offset, avp_data_length, ENC_UTF_8|ENC_NA);
                                        break;
                                }
                                case PANA_OCTET_STRING: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_bytes, tvb,
                                                            offset, avp_data_length, ENC_NA);
                                        break;
                                }
                                case PANA_INTEGER32: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int32, tvb,
                                                            offset, 4, ENC_BIG_ENDIAN);
                                        break;
                                }
                                case PANA_UNSIGNED32: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint32, tvb,
                                                            offset, 4, ENC_BIG_ENDIAN);
                                        break;
                                }
                                case PANA_INTEGER64: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int64, tvb,
                                                            offset, 8, ENC_BIG_ENDIAN);
                                        break;
                                }
                                case PANA_UNSIGNED64: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint64, tvb,
                                                            offset, 8, ENC_BIG_ENDIAN);
                                        break;
                                }
                                case PANA_ENUMERATED: {
                                        proto_tree_add_item(single_avp_tree, hf_pana_avp_data_enumerated, tvb,
                                                            offset, 4, ENC_BIG_ENDIAN);
                                        break;
                                }
                                case PANA_RESULT_CODE: {
                                        result_code = tvb_get_ntohl(tvb, offset);
                                        proto_tree_add_uint_format(single_avp_tree, hf_pana_avp_code, tvb, offset, avp_data_length,
                                                                   result_code, "Value: %d (%s)",
                                                                   result_code,
                                                                   val_to_str(result_code, avp_code_names, "Unknown (%d)"));
                                        break;
                                }
                                case PANA_EAP: {
                                        avp_eap_tree = proto_tree_add_subtree(single_avp_tree,
                                                                              tvb, offset, avp_data_length,
                                                                              ett_pana_avp, NULL, "AVP Value (EAP packet)");
                                        eap_tvb = tvb_new_subset_length(tvb, offset, avp_data_length);
                                        DISSECTOR_ASSERT_HINT(eap_handle, "EAP Dissector not available");
                                        call_dissector(eap_handle, eap_tvb, pinfo, avp_eap_tree);
                                        break;
                                }
                                case PANA_ENCAPSULATED: {
                                        avp_encap_tree = proto_tree_add_subtree(single_avp_tree,
                                                                                tvb, offset, avp_data_length,
                                                                                ett_pana_avp, NULL, "AVP Value (PANA packet)");
                                        encap_tvb = tvb_new_subset_length(tvb, offset, avp_data_length);
                                        dissect_pana_pdu(encap_tvb, pinfo, avp_encap_tree);
                                        break;
                                }
                        }
                }
                offset += avp_data_length + padding;

                /* Update the buffer length */
                buffer_length -=  avp_length + padding;
        }

}
コード例 #4
0
/*
 * Function for AVP dissector.
 */
static void
dissect_avps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *avp_tree)
{

       gint offset;
       guint16 avp_code;
       guint16 avp_flags;
       guint16 avp_length;
       guint16 avp_type;
       guint32 vendor_id;
       guint16 avp_hdr_length;
       guint16 avp_data_length;
       guint16 padding;

       guint16 buffer_length;
       int bad_avp = FALSE;

       tvbuff_t *group_tvb;
       tvbuff_t *eap_tvb;
       proto_item *single_avp_item;
       proto_tree *single_avp_tree;
       proto_item *avp_group_item;
       proto_tree *avp_group_tree;
       proto_item *avp_eap_item;
       proto_tree *avp_eap_tree;

       offset = 0;
       buffer_length = tvb_reported_length(tvb);

       /* Go through all AVPs */
       while (buffer_length > 0) {
               avp_code = tvb_get_ntohs(tvb, offset);
               avp_flags = tvb_get_ntohs(tvb, offset + 2);
               avp_length = tvb_get_ntohs(tvb, offset + 4);

               /* Check AVP flags for vendor specific AVP */
               if (avp_flags & PANA_AVP_FLAG_V) {
                       vendor_id = tvb_get_ntohl(tvb, 8);
                       avp_hdr_length = 12;
               } else {
                       vendor_id = 0;
                       avp_hdr_length = 8;
               }

               /* Check AVP type */
               avp_type = pana_avp_get_type(avp_code, vendor_id);

               /* Check AVP length */
               if (avp_length < avp_hdr_length) {
                       single_avp_item = proto_tree_add_text(avp_tree, tvb, offset, avp_length,
                                                             "%s (%s) length: %d bytes (shorter than header length %d)",
                                                             val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
                                                             val_to_str(avp_type, avp_type_names, "Unknown (%d)"),
                                                             avp_length,
                                                             avp_hdr_length);

                       single_avp_tree = proto_item_add_subtree(single_avp_item, ett_pana_avp_info);

                       if (single_avp_tree != NULL) {
                               /* AVP Code */
                               proto_tree_add_uint_format_value(single_avp_tree, hf_pana_avp_code, tvb,
                                                                offset, 2, avp_code, "%s (%u)",
                                                                val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
                                                                avp_code);
                               offset += 2;
                               /* AVP Flags */
                               dissect_pana_avp_flags(single_avp_tree, tvb, offset, avp_flags);
                               offset += 2;
                               /* AVP Length */
                               proto_tree_add_item(single_avp_tree, hf_pana_avp_length, tvb, offset, 2, FALSE);
                               offset += 2;
                       }
                       return;
               }

               /* Check AVP flags */
               if (avp_flags & PANA_AVP_FLAG_RES) bad_avp = TRUE;

               /* Check padding */
               padding = (4 - (avp_length % 4)) % 4;

               single_avp_item = proto_tree_add_text(avp_tree, tvb, offset, avp_length + padding,
                                                               "%s (%s) length: %d bytes (%d padded bytes)",
                                                               val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
                                                               val_to_str(avp_type, avp_type_names, "Unknown (%d)"),
                                                               avp_length,
                                                               avp_length + padding);

               single_avp_tree = proto_item_add_subtree(single_avp_item, ett_pana_avp_info);

               /* AVP data length */
               avp_data_length = avp_length - avp_hdr_length;

               if (single_avp_tree != NULL) {
                       /* AVP Code */
                       proto_tree_add_uint_format_value(single_avp_tree, hf_pana_avp_code, tvb,
                                                       offset, 2, avp_code, "%s (%u)",
                                                       val_to_str(avp_code, avp_code_names, "Unknown (%d)"),
                                                       avp_code);
               }
               offset += 2;
               if (single_avp_tree != NULL) {
                       /* AVP Flags */
                       dissect_pana_avp_flags(single_avp_tree, tvb, offset, avp_flags);
               }
               offset += 2;
               if (single_avp_tree != NULL) {
                       /* AVP Length */
                       proto_tree_add_item(single_avp_tree, hf_pana_avp_length, tvb, offset, 2, FALSE);
               }
               offset += 2;
               if (single_avp_tree != NULL) {
                       /* Reserved */
                       proto_tree_add_item(single_avp_tree, hf_pana_avp_reserved, tvb, offset, 2, FALSE);
               }
               offset += 2;
               if (avp_flags & PANA_AVP_FLAG_V) {
                       if (single_avp_tree != NULL) {
                               /* Vendor ID */
                               proto_tree_add_item(single_avp_tree, hf_pana_avp_vendorid, tvb, offset, 4, FALSE);
                       }
                       offset += 4;
               }
               if (avp_flags & PANA_AVP_FLAG_V) {
                       /* AVP Value */
                       switch(avp_type) {
                               case PANA_GROUPED: {
                                       avp_group_item = proto_tree_add_text(single_avp_tree,
                                                                         tvb, offset, avp_data_length,
                                                                         "Grouped AVP");
                                       avp_group_tree = proto_item_add_subtree(avp_group_item, ett_pana_avp);
                                       group_tvb = tvb_new_subset(tvb, offset,
                                                                       MIN(avp_data_length, tvb_length(tvb)-offset), avp_data_length);
                                       if (avp_group_tree != NULL) {
                                               dissect_avps(group_tvb, pinfo, avp_group_tree);
                                       }
                                       break;
                               }
                               case PANA_UTF8STRING: {
                                       const guint8 *data;
                                       data = tvb_get_ptr(tvb, offset, avp_data_length);
                                       proto_tree_add_string_format(single_avp_tree, hf_pana_avp_data_string, tvb,
                                                       offset, avp_data_length, data,
                                                       "UTF8String: %*.*s",
                                                       avp_data_length, avp_data_length, data);
                                       break;
                               }
                               case PANA_OCTET_STRING: {
                                       proto_tree_add_bytes_format(single_avp_tree, hf_pana_avp_data_bytes, tvb,
                                                       offset, avp_data_length,
                                                   tvb_get_ptr(tvb, offset, avp_data_length),
                                                       "Hex Data Highlighted Below");
                                       break;
                               }
                               case PANA_INTEGER32: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int32, tvb,
                                                       offset, 4, FALSE);
                                       break;
                               }
                               case PANA_UNSIGNED32: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint32, tvb,
                                                       offset, 4, FALSE);
                                       break;
                               }
                               case PANA_INTEGER64: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_int64, tvb,
                                                       offset, 8, FALSE);
                                       break;
                               }
                               case PANA_UNSIGNED64: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_uint64, tvb,
                                                       offset, 8, FALSE);
                                       break;
                               }
                               case PANA_ENUMERATED: {
                                       proto_tree_add_item(single_avp_tree, hf_pana_avp_data_enumerated, tvb,
                                                       offset, 4, FALSE);
                                       break;
                               }
                               case PANA_RESULT_CODE: {
                                       proto_tree_add_text(single_avp_tree, tvb, offset, avp_data_length,
                                                               "Value: %d (%s)",
                                                               tvb_get_ntohl(tvb, offset),
                                                               val_to_str(tvb_get_ntohs(tvb, offset), avp_code_names, "Unknown (%d)"));
                                       break;
                               }
                               case PANA_EAP: {
                                       avp_eap_item = proto_tree_add_text(single_avp_tree,
                                                                         tvb, offset, avp_data_length,
                                                                         "AVP Value (EAP packet)");
                                       avp_eap_tree = proto_item_add_subtree(avp_eap_item, ett_pana_avp);
                                       eap_tvb = tvb_new_subset(tvb, offset, avp_data_length, avp_data_length);
                                       if (eap_handle != NULL) {
                                               call_dissector(eap_handle, eap_tvb, pinfo, avp_eap_tree);
                                       }
                                       break;
                               }
                       }
               }
               offset += avp_data_length + padding;

               /* Update the buffer length */
               buffer_length -=  avp_length + padding;
       }

}