Exemplo n.º 1
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;
        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;
        }

}
Exemplo n.º 2
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;
       }

}