Ejemplo n.º 1
0
static void
dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
    gboolean is_tcp)
{
    proto_tree            *ncp_tree = NULL;
    proto_item            *ti;
    struct ncp_ip_header  ncpiph;
    struct ncp_ip_rqhdr   ncpiphrq;
    guint16               ncp_burst_seqno, ncp_ack_seqno;
    guint16               flags = 0;
    proto_tree            *flags_tree = NULL;
    int                   hdr_offset = 0;
    int                   commhdr = 0;
    int                   offset = 0;
    gint                  length_remaining;
    tvbuff_t              *next_tvb;
    guint32               testvar = 0, ncp_burst_command, burst_len, burst_off, burst_file;
    guint8                subfunction;
    guint32               nw_connection = 0, data_offset;
    guint16               data_len = 0;
    guint16               missing_fraglist_count = 0;
    mncp_rhash_value      *request_value = NULL;
    conversation_t        *conversation;
    proto_item            *expert_item;

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

    ncp_hdr = &header;

    ti = proto_tree_add_item(tree, proto_ncp, tvb, 0, -1, ENC_NA);
    ncp_tree = proto_item_add_subtree(ti, ett_ncp);
    if (is_tcp) {
        if (tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RQST && tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RPLY)
            commhdr += 1;
        /* Get NCPIP Header data */
        ncpiph.signature = tvb_get_ntohl(tvb, commhdr);
        proto_tree_add_uint(ncp_tree, hf_ncp_ip_sig, tvb, commhdr, 4, ncpiph.signature);
        ncpiph.length = (0x7fffffff & tvb_get_ntohl(tvb, commhdr+4));
        proto_tree_add_uint(ncp_tree, hf_ncp_ip_length, tvb, commhdr+4, 4, ncpiph.length);
        commhdr += 8;
        if (ncpiph.signature == NCPIP_RQST) {
            ncpiphrq.version = tvb_get_ntohl(tvb, commhdr);
            proto_tree_add_uint(ncp_tree, hf_ncp_ip_ver, tvb, commhdr, 4, ncpiphrq.version);
            commhdr += 4;
            ncpiphrq.rplybufsize = tvb_get_ntohl(tvb, commhdr);
            proto_tree_add_uint(ncp_tree, hf_ncp_ip_rplybufsize, tvb, commhdr, 4, ncpiphrq.rplybufsize);
            commhdr += 4;
        }
        /* Check to see if this is a valid offset, otherwise increment for packet signature */
        if (try_val_to_str(tvb_get_ntohs(tvb, commhdr), ncp_type_vals)==NULL) {
            /* Check to see if we have a valid type after packet signature length */
            if (try_val_to_str(tvb_get_ntohs(tvb, commhdr+8), ncp_type_vals)!=NULL) {
                proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, commhdr, 8, ENC_NA);
                commhdr += 8;
            }
        }
    } else {
        /* Initialize this structure, we use it below */
        memset(&ncpiph, 0, sizeof(ncpiph));
    }

    header.type         = tvb_get_ntohs(tvb, commhdr);
    header.sequence     = tvb_get_guint8(tvb, commhdr+2);
    header.conn_low     = tvb_get_guint8(tvb, commhdr+3);
    header.task         = tvb_get_guint8(tvb, commhdr+4);
    header.conn_high    = tvb_get_guint8(tvb, commhdr+5);
    proto_tree_add_uint(ncp_tree, hf_ncp_type, tvb, commhdr, 2, header.type);
    nw_connection = (header.conn_high*256)+header.conn_low;

    /* Ok, we need to track the conversation so that we can
     * determine if a new server session is occuring for this
     * connection.
     */
    conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
        PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport,
        0);
    if ((ncpiph.length & 0x80000000) || ncpiph.signature == NCPIP_RPLY) {
        /* First time through we will record the initial connection and task
         * values
         */
        if (!pinfo->fd->flags.visited) {
            if (conversation != NULL) {
                /* find the record telling us the
                 * request made that caused this
                 * reply
                 */
                request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
                /* if for some reason we have no
                 * conversation in our hash, create
                 * one */
                if (request_value == NULL) {
                    mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
                }
            } else {
                /* It's not part of any conversation
                 * - create a new one.
                 */
                conversation = conversation_new(pinfo->fd->num, &pinfo->src,
                    &pinfo->dst, PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0);
                mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
            }
            /* If this is a request packet then we
             * might have a new task
             */
            if (ncpiph.signature == NCPIP_RPLY) {
                /* Now on reply packets we have to
                 * use the state of the original
                 * request packet, so look up the
                 * request value and check the task number
                 */
                /*request_value = mncp_hash_lookup(conversation, nw_connection, header.task);*/
            }
        } else {
            /* Get request value data */
            request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
            if (request_value) {
                if ((request_value->session_start_packet_num == pinfo->fd->num) && ncp_echo_conn) {
                    expert_add_info_format(pinfo, NULL, &ei_ncp_new_server_session, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task);
                }
            }
        }
    } else {
        if (!pinfo->fd->flags.visited) {
            if (conversation != NULL) {
                /* find the record telling us the
                 * request made that caused this
                 * reply
                 */
                request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
                /* if for some reason we have no
                 * conversation in our hash, create
                 * one */
                if (request_value == NULL) {
                    mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
                }
            } else {
                /* It's not part of any conversation
                 * - create a new one.
                 */
                conversation = conversation_new(pinfo->fd->num, &pinfo->src,
                    &pinfo->dst, PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0);
                mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
            }
            /* find the record telling us the request
             * made that caused this reply
             */
        } else {
            request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
            if (request_value) {
                if ((request_value->session_start_packet_num == pinfo->fd->num) && ncp_echo_conn) {
                    expert_add_info_format(pinfo, NULL, &ei_ncp_new_server_session, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task);
                }
            }
        }
    }

    tap_queue_packet(ncp_tap.hdr, pinfo, ncp_hdr);

    col_add_str(pinfo->cinfo, COL_INFO,
        val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)"));

    /*
     * Process the packet-type-specific header.
     */
    switch (header.type) {

    case NCP_BROADCAST_SLOT:    /* Server Broadcast */
        proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence);
        proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
        proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_oplock_flag, tvb, commhdr + 9, 1, tvb_get_guint8(tvb, commhdr+9));
        proto_tree_add_item(ncp_tree, hf_ncp_oplock_handle, tvb, commhdr + 10, 4, ENC_BIG_ENDIAN);
        if ((tvb_get_guint8(tvb, commhdr+9)==0x24) && ncp_echo_file) {
            expert_add_info_format(pinfo, NULL, &ei_ncp_oplock_handle, "Server requesting station to clear oplock on handle - %08x", tvb_get_ntohl(tvb, commhdr+10));
        }
        break;

    case NCP_LIP_ECHO:    /* Lip Echo Packet */
        proto_tree_add_item(ncp_tree, hf_lip_echo, tvb, commhdr, 13, ENC_ASCII|ENC_NA);
        break;

    case NCP_BURST_MODE_XFER:    /* Packet Burst Packet */
        /*
         * XXX - we should keep track of whether there's a burst
         * outstanding on a connection and, if not, treat the
         * beginning of the data as a burst header.
         *
         * The burst header contains:
         *
         *    4 bytes of little-endian function number:
         *        1 = read, 2 = write;
         *
         *    4 bytes of file handle;
         *
         *    8 reserved bytes;
         *
         *    4 bytes of big-endian file offset;
         *
         *    4 bytes of big-endian byte count.
         *
         * The data follows for a burst write operation.
         *
         * The first packet of a burst read reply contains:
         *
         *    4 bytes of little-endian result code:
         *       0: No error
         *       1: Initial error
         *       2: I/O error
         *       3: No data read;
         *
         *    4 bytes of returned byte count (big-endian?).
         *
         * The data follows.
         *
         * Each burst of a write request is responded to with a
         * burst packet with a 2-byte little-endian result code:
         *
         *    0: Write successful
         *    4: Write error
         */
        flags = tvb_get_guint8(tvb, commhdr + 2);

        ti = proto_tree_add_uint(ncp_tree, hf_ncp_system_flags,
            tvb, commhdr + 2, 1, flags);
        flags_tree = proto_item_add_subtree(ti, ett_ncp_system_flags);

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_abt,
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
        if (flags & ABT) {
            proto_item_append_text(ti, "  ABT");
        }
        flags&=(~( ABT ));

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_bsy,
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
        if (flags & BSY) {
            proto_item_append_text(ti, "  BSY");
        }
        flags&=(~( BSY ));

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_eob,
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
        if (flags & EOB) {
            proto_item_append_text(ti, "  EOB");
        }
        flags&=(~( EOB ));

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_lst,
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
        if (flags & LST) {
            proto_item_append_text(ti, "  LST");
        }
        flags&=(~( LST ));

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_sys,
            tvb, commhdr + 2, 1, ENC_BIG_ENDIAN);
        if (flags & SYS) {
            proto_item_append_text(ti, "  SYS");
        }
        flags&=(~( SYS ));


        proto_tree_add_item(ncp_tree, hf_ncp_stream_type,
            tvb, commhdr + 3, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_src_connection,
            tvb, commhdr + 4, 4, ENC_BIG_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_dst_connection,
            tvb, commhdr + 8, 4, ENC_BIG_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_packet_seqno,
            tvb, commhdr + 12, 4, ENC_BIG_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_delay_time,
            tvb, commhdr + 16, 4, ENC_BIG_ENDIAN);
        ncp_burst_seqno = tvb_get_ntohs(tvb, commhdr+20);
        proto_tree_add_item(ncp_tree, hf_ncp_burst_seqno,
            tvb, commhdr + 20, 2, ENC_BIG_ENDIAN);
        ncp_ack_seqno = tvb_get_ntohs(tvb, commhdr+22);
        proto_tree_add_item(ncp_tree, hf_ncp_ack_seqno,
            tvb, commhdr + 22, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_burst_len,
            tvb, commhdr + 24, 4, ENC_BIG_ENDIAN);
        data_offset = tvb_get_ntohl(tvb, commhdr + 28);
        proto_tree_add_uint(ncp_tree, hf_ncp_data_offset,
            tvb, commhdr + 28, 4, data_offset);
        data_len = tvb_get_ntohs(tvb, commhdr + 32);
        proto_tree_add_uint(ncp_tree, hf_ncp_data_bytes,
            tvb, commhdr + 32, 2, data_len);
        missing_fraglist_count = tvb_get_ntohs(tvb, commhdr + 34);
        proto_tree_add_item(ncp_tree, hf_ncp_missing_fraglist_count,
            tvb, commhdr + 34, 2, ENC_BIG_ENDIAN);
        offset = commhdr + 36;
        if (!(flags & SYS) && ncp_burst_seqno == ncp_ack_seqno &&
            data_offset == 0) {
            /*
             * This is either a Burst Read or Burst Write
             * command.  The data length includes the burst
             * mode header, plus any data in the command
             * (there shouldn't be any in a read, but there
             * might be some in a write).
             */
            if (data_len < 4)
                return;
            ncp_burst_command = tvb_get_ntohl(tvb, offset);
            proto_tree_add_item(ncp_tree, hf_ncp_burst_command,
                tvb, offset, 4, ENC_BIG_ENDIAN);
            offset += 4;
            data_len -= 4;

            if (data_len < 4)
                return;
            burst_file = tvb_get_ntohl(tvb, offset);
            proto_tree_add_item(ncp_tree, hf_ncp_burst_file_handle,
                tvb, offset, 4, ENC_BIG_ENDIAN);
            offset += 4;
            data_len -= 4;

            if (data_len < 8)
                return;
            proto_tree_add_item(ncp_tree, hf_ncp_burst_reserved,
                tvb, offset, 8, ENC_NA);
            offset += 8;
            data_len -= 8;

            if (data_len < 4)
                return;
            burst_off = tvb_get_ntohl(tvb, offset);
            proto_tree_add_uint(ncp_tree, hf_ncp_burst_offset,
                tvb, offset, 4, burst_off);
            offset += 4;
            data_len -= 4;

            if (data_len < 4)
                return;
            burst_len = tvb_get_ntohl(tvb, offset);
            proto_tree_add_uint(ncp_tree, hf_ncp_burst_len,
                tvb, offset, 4, burst_len);
            offset += 4;
            data_len -= 4;

            col_add_fstr(pinfo->cinfo, COL_INFO,
                "%s %d bytes starting at offset %d in file 0x%08x",
                val_to_str(ncp_burst_command,
                    burst_command, "Unknown (0x%08x)"),
                    burst_len, burst_off, burst_file);
            break;
        } else {
            if (tvb_get_guint8(tvb, commhdr + 2) & 0x10) {
                col_set_str(pinfo->cinfo, COL_INFO, "End of Burst");
            }
        }
        break;

    case NCP_ALLOCATE_SLOT:        /* Allocate Slot Request */
        length_remaining = tvb_length_remaining(tvb, commhdr + 4);
        if (length_remaining > 4) {
            testvar = tvb_get_ntohl(tvb, commhdr+4);
            if (testvar == 0x4c495020) {
                proto_tree_add_item(ncp_tree, hf_lip_echo, tvb, commhdr+4, 13, ENC_ASCII|ENC_NA);
                break;
            }
        }
        /* otherwise fall through */

    case NCP_POSITIVE_ACK:        /* Positive Acknowledgement */
    case NCP_SERVICE_REQUEST:    /* Server NCP Request */
    case NCP_SERVICE_REPLY:        /* Server NCP Reply */
    case NCP_WATCHDOG:        /* Watchdog Packet */
    case NCP_DEALLOCATE_SLOT:    /* Deallocate Slot Request */
    default:
        proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence);
        proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
        proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, ENC_BIG_ENDIAN);
        break;
    }

    /*
     * Process the packet body.
     */
    switch (header.type) {

    case NCP_ALLOCATE_SLOT:        /* Allocate Slot Request */
        length_remaining = tvb_length_remaining(tvb, commhdr + 4);
        if (length_remaining > 4) {
            testvar = tvb_get_ntohl(tvb, commhdr+4);
            if (testvar == 0x4c495020) {
                proto_tree_add_text(ncp_tree, tvb, commhdr, -1,
                    "Lip Echo Packet");
                /*break;*/
            }
        }
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        dissect_ncp_request(next_tvb, pinfo, nw_connection,
            header.sequence, header.type, ncp_tree);
        break;

    case NCP_DEALLOCATE_SLOT:    /* Deallocate Slot Request */
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        dissect_ncp_request(next_tvb, pinfo, nw_connection,
            header.sequence, header.type, ncp_tree);
        break;

    case NCP_SERVICE_REQUEST:    /* Server NCP Request */
    case NCP_BROADCAST_SLOT:    /* Server Broadcast Packet */
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        if (tvb_get_guint8(tvb, commhdr+6) == 0x68) {
            subfunction = tvb_get_guint8(tvb, commhdr+7);
            switch (subfunction) {

            case 0x02:    /* NDS Frag Packet to decode */
                dissect_nds_request(next_tvb, pinfo,
                    nw_connection, header.sequence,
                    header.type, ncp_tree);
                break;

            case 0x01:    /* NDS Ping */
                dissect_ping_req(next_tvb, pinfo,
                    nw_connection, header.sequence,
                    header.type, ncp_tree);
                break;

            default:
                dissect_ncp_request(next_tvb, pinfo,
                    nw_connection, header.sequence,
                    header.type, ncp_tree);
                break;
             }
        } else {
            dissect_ncp_request(next_tvb, pinfo, nw_connection,
                header.sequence, header.type, ncp_tree);
        }
        break;

    case NCP_SERVICE_REPLY:        /* Server NCP Reply */
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        nds_defrag(next_tvb, pinfo, nw_connection, header.sequence,
            header.type, ncp_tree, &ncp_tap);
        break;

    case NCP_POSITIVE_ACK:        /* Positive Acknowledgement */
        /*
         * XXX - this used to call "nds_defrag()", which would
         * clear out "frags".  Was that the right thing to
         * do?
         */
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        dissect_ncp_reply(next_tvb, pinfo, nw_connection,
            header.sequence, header.type, ncp_tree, &ncp_tap);
        break;

    case NCP_WATCHDOG:        /* Watchdog Packet */
        /*
         * XXX - should the completion code be interpreted as
         * it is in "packet-ncp2222.inc"?  If so, this
         * packet should be handled by "dissect_ncp_reply()".
         */
        proto_tree_add_item(ncp_tree, hf_ncp_completion_code,
            tvb, commhdr + 6, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_connection_status,
            tvb, commhdr + 7, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_slot,
            tvb, commhdr + 8, 1, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(ncp_tree, hf_ncp_control_code,
            tvb, commhdr + 9, 1, ENC_LITTLE_ENDIAN);
        /*
         * Display the rest of the packet as data.
         */
        if (tvb_offset_exists(tvb, commhdr + 10)) {
            call_dissector(data_handle,
                tvb_new_subset_remaining(tvb, commhdr + 10),
                pinfo, ncp_tree);
        }
        break;

    case NCP_BURST_MODE_XFER:    /* Packet Burst Packet */
        if (flags & SYS) {
            /*
             * System packet; show missing fragments if there
             * are any.
             */
            while (missing_fraglist_count != 0) {
                proto_tree_add_item(ncp_tree, hf_ncp_missing_data_offset,
                    tvb, offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
                proto_tree_add_item(ncp_tree, hf_ncp_missing_data_count,
                    tvb, offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                missing_fraglist_count--;
            }
        } else {
            /*
             * XXX - do this by using -1 and -1 as the length
             * arguments to "tvb_new_subset()" and then calling
             * "tvb_set_reported_length()"?  That'll throw an
             * exception if "data_len" goes past the reported
             * length of the packet, but that's arguably a
             * feature in this case.
             */
            length_remaining = tvb_length_remaining(tvb, offset);
            if (length_remaining > data_len)
                length_remaining = data_len;
            if (data_len != 0) {
                call_dissector(data_handle,
                    tvb_new_subset(tvb, offset,
                    length_remaining, data_len),
                    pinfo, ncp_tree);
            }
        }
        break;

    case NCP_LIP_ECHO:        /* LIP Echo Packet */
        proto_tree_add_text(ncp_tree, tvb, commhdr, -1,
            "Lip Echo Packet");
        break;

    default:
        expert_item = proto_tree_add_text(ncp_tree, tvb, commhdr + 6, -1,
            "%s packets not supported yet",
            val_to_str(header.type, ncp_type_vals,
                "Unknown type (0x%04x)"));
        if (ncp_echo_err) {
            expert_add_info_format(pinfo, expert_item, &ei_ncp_type, "%s packets not supported yet", val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)"));
        }
        break;
    }
}
Ejemplo n.º 2
0
/*
 * Call this method to actually dissect the multipart body.
 * NOTE - Only do so if a boundary string has been found!
 */
static int dissect_multipart(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
    proto_tree *subtree;
    proto_item *ti;
    proto_item *type_ti;
    multipart_info_t *m_info = get_multipart_info(pinfo, (const char*)data);
    gint header_start = 0;
    gint body_index = 0;
    gboolean last_boundary = FALSE;

    if (m_info == NULL) {
        /*
         * We can't get the required multipart information
         */
        proto_tree_add_expert(tree, pinfo, &ei_multipart_no_required_parameter, tvb, 0, -1);
        call_dissector(data_handle, tvb, pinfo, tree);
        return tvb_reported_length(tvb);
    }
    /* Clean up the memory if an exception is thrown */
    /* CLEANUP_PUSH(cleanup_multipart_info, m_info); */

    /* Add stuff to the protocol tree */
    ti = proto_tree_add_item(tree, proto_multipart,
                             tvb, 0, -1, ENC_NA);
    subtree = proto_item_add_subtree(ti, ett_multipart);
    proto_item_append_text(ti, ", Type: %s, Boundary: \"%s\"",
                           m_info->type, m_info->boundary);

    /* Show multi-part type as a generated field */
    type_ti = proto_tree_add_string(subtree, hf_multipart_type,
                                    tvb, 0, 0, pinfo->match_string);
    PROTO_ITEM_SET_GENERATED(type_ti);

    /*
     * Make no entries in Protocol column and Info column on summary display,
     * but stop sub-dissectors from clearing entered text in summary display.
     */
    col_set_fence(pinfo->cinfo, COL_INFO);

    /*
     * Process the multipart preamble
     */
    header_start = process_preamble(subtree, tvb, m_info, &last_boundary);
    if (header_start == -1) {
        call_dissector(data_handle, tvb, pinfo, subtree);
        /* Clean up the dynamically allocated memory */
        cleanup_multipart_info(m_info);
        return tvb_reported_length(tvb);
    }
    /*
     * Process the encapsulated bodies
     */
    while (last_boundary == FALSE) {
        header_start = process_body_part(subtree, tvb, m_info,
                                         pinfo, header_start, body_index++, &last_boundary);
        if (header_start == -1) {
            /* Clean up the dynamically allocated memory */
            cleanup_multipart_info(m_info);
            return tvb_reported_length(tvb);
        }
    }
    /*
     * Process the multipart trailer
     */
    if (tvb_reported_length_remaining(tvb, header_start) > 0) {
        proto_tree_add_item(subtree, hf_multipart_trailer, tvb, header_start, -1, ENC_NA);
    }
    /* Clean up the dynamically allocated memory */
    cleanup_multipart_info(m_info);
    return tvb_reported_length(tvb);
}
Ejemplo n.º 3
0
void
ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype,
	  packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
	  int etype_id, int trailer_id, int fcs_len)
{
	const char		*description;
	tvbuff_t		*volatile next_tvb;
	guint			length_before;
	gint			captured_length, reported_length;
	volatile gboolean	dissector_found = FALSE;
	const char		*volatile saved_proto;
	void			*pd_save;

	/* Add the Ethernet type to the protocol tree */
	if (tree) {
		proto_tree_add_uint(fh_tree, etype_id, tvb,
				    offset_after_etype - 2, 2, etype);
	}

	/* Get the captured length and reported length of the data
	   after the Ethernet type. */
	captured_length = tvb_length_remaining(tvb, offset_after_etype);
	reported_length = tvb_reported_length_remaining(tvb,
							offset_after_etype);

	/* Remember how much data there is after the Ethernet type,
	   including any trailer and FCS. */
	length_before = reported_length;

	/* Construct a tvbuff for the payload after the Ethernet type.
	   If the FCS length is positive, remove the FCS.
	   (If it's zero, there's no FCS; if it's negative,
	   we don't know whether there's an FCS, so we'll
	   guess based on the length of the trailer.) */
	if (fcs_len > 0) {
		if (captured_length >= 0 && reported_length >= 0) {
			if (reported_length >= fcs_len)
				reported_length -= fcs_len;
			if (captured_length > reported_length)
				captured_length = reported_length;
		}
	}
	next_tvb = tvb_new_subset(tvb, offset_after_etype, captured_length,
				  reported_length);

	pinfo->ethertype = etype;

	/* Look for sub-dissector, and call it if found.
	   Catch exceptions, so that if the reported length of "next_tvb"
	   was reduced by some dissector before an exception was thrown,
	   we can still put in an item for the trailer. */
	saved_proto = pinfo->current_proto;
	pd_save = pinfo->private_data;
	TRY {
		dissector_found = dissector_try_uint(ethertype_dissector_table,
						     etype, next_tvb, pinfo, tree);
	}
	CATCH(BoundsError) {
		/* Somebody threw BoundsError, which means that:

		   1) a dissector was found, so we don't need to
		   dissect the payload as data or update the
		   protocol or info columns;

		   2) dissecting the payload found that the packet was
		   cut off by a snapshot length before the end of
		   the payload.  The trailer comes after the payload,
		   so *all* of the trailer is cut off, and we'll
		   just get another BoundsError if we add the trailer.

		   Therefore, we just rethrow the exception so it gets
		   reported; we don't dissect the trailer or do anything
		   else. */
		RETHROW;
	}
	CATCH(OutOfMemoryError) {
		RETHROW;
	}
	CATCH_ALL {
		/* Somebody threw an exception other than BoundsError, which
		   means that a dissector was found, so we don't need to
		   dissect the payload as data or update the protocol or info
		   columns.  We just show the exception and then drive on
		   to show the trailer, after noting that a dissector was
		   found and restoring the protocol value that was in effect
		   before we called the subdissector. */
		show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);

		/*  Restore the private_data structure in case one of the
		 *  called dissectors modified it (and, due to the exception,
		 *  was unable to restore it).
		 */
		pinfo->private_data = pd_save;
		dissector_found = TRUE;
		pinfo->current_proto = saved_proto;
	}
	ENDTRY;

	if (!dissector_found) {
		/* No sub-dissector found.
		   Label rest of packet as "Data" */
		call_dissector(data_handle,next_tvb, pinfo, tree);

		/* Label protocol */
		col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", etype);

		description = match_strval(etype, etype_vals);
		if (description) {
			col_add_str(pinfo->cinfo, COL_INFO, description);
		}
	}

	add_dix_trailer(pinfo, tree, fh_tree, trailer_id, tvb, next_tvb, offset_after_etype,
			length_before, fcs_len);
}
Ejemplo n.º 4
0
static void
dissect_hci_h4(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint8      type;
	tvbuff_t    *next_tvb;
	proto_item  *ti = NULL;
	proto_tree  *hci_h4_tree = NULL;
	void        *pd_save;
	hci_data_t  *hci_data;

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "HCI H4");
	switch (pinfo->p2p_dir) {

	case P2P_DIR_SENT:
		col_add_fstr(pinfo->cinfo, COL_INFO, "Sent ");
		break;

	case P2P_DIR_RECV:
		col_add_fstr(pinfo->cinfo, COL_INFO, "Rcvd ");
		break;

	case P2P_DIR_UNKNOWN:
		break;

	default:
		col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
				pinfo->p2p_dir);
		break;
	}

	type = tvb_get_guint8(tvb, 0);

	if(tree){
		ti = proto_tree_add_item(tree, proto_hci_h4, tvb, 0, 1, ENC_NA);
		hci_h4_tree = proto_item_add_subtree(ti, ett_hci_h4);
	}

	pd_save = pinfo->private_data;
	hci_data = ep_alloc(sizeof(hci_data_t));
	hci_data->interface_id = HCI_INTERFACE_H4;
	hci_data->adapter_id = HCI_ADAPTER_DEFAULT;
	hci_data->chandle_to_bdaddr_table = chandle_to_bdaddr_table;
	hci_data->bdaddr_to_name_table = bdaddr_to_name_table;
	hci_data->localhost_bdaddr = localhost_bdaddr;
	hci_data->localhost_name = localhost_name;
	pinfo->private_data = hci_data;

	ti=proto_tree_add_uint(hci_h4_tree, hf_hci_h4_direction, tvb, 0, 0, pinfo->p2p_dir);
	PROTO_ITEM_SET_GENERATED(ti);

	proto_tree_add_item(hci_h4_tree, hf_hci_h4_type,
		tvb, 0, 1, ENC_LITTLE_ENDIAN);
	col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
			val_to_str(type, hci_h4_type_vals, "Unknown HCI packet type 0x%02x"));

	next_tvb = tvb_new_subset_remaining(tvb, 1);
	if(!dissector_try_uint(hci_h4_table, type, next_tvb, pinfo, tree)) {
		call_dissector(data_handle, next_tvb, pinfo, tree);
	}

	pinfo->private_data = pd_save;
}
Ejemplo n.º 5
0
static void
dissect_netrom_proto(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item   *ti;
	proto_tree   *netrom_tree;
	int           offset;
#if 0
	guint8        src_ssid;
	guint8        dst_ssid;
#endif
	guint8        op_code;
	guint8        cct_index;
	guint8        cct_id;
	tvbuff_t     *next_tvb;

	col_set_str( pinfo->cinfo, COL_PROTOCOL, "NET/ROM" );
	col_clear( pinfo->cinfo, COL_INFO );

	offset = 0;

	/* source */
	set_address_tvb(&pinfo->dl_src,	AT_AX25, AX25_ADDR_LEN, tvb, offset);
	set_address_tvb(&pinfo->src,	AT_AX25, AX25_ADDR_LEN, tvb, offset);
	/* src_ssid = tvb_get_guint8(tvb, offset+6); */
	offset += AX25_ADDR_LEN; /* step over src addr */

	/* destination */
	set_address_tvb(&pinfo->dl_dst,	AT_AX25, AX25_ADDR_LEN, tvb, offset);
	set_address_tvb(&pinfo->dst,	AT_AX25, AX25_ADDR_LEN, tvb, offset);
	/* dst_ssid = tvb_get_guint8(tvb, offset+6); */
	offset += AX25_ADDR_LEN; /* step over dst addr */

	offset += 1; /* step over ttl */
	cct_index =  tvb_get_guint8( tvb, offset );
	offset += 1; /* step over cct index*/
	cct_id =  tvb_get_guint8( tvb, offset );
	offset += 1; /* step over cct id */
	offset += 1; /* step over n_s */
	offset += 1; /* step over n_r */

	/* frame type */
	op_code =  tvb_get_guint8( tvb, offset ) & 0x0f;
	/*offset += 1;*/ /* step over op_code */

	col_add_fstr( pinfo->cinfo, COL_INFO, "%s", val_to_str_const( op_code, op_code_vals_text, "Unknown" ));

	/* if ( tree ) */
		{
		/* create display subtree for the protocol */

		ti = proto_tree_add_protocol_format( tree, proto_netrom, tvb, 0, NETROM_HEADER_SIZE,
			"NET/ROM, Src: %s, Dst: %s",
			address_to_str(wmem_packet_scope(), &pinfo->src),
			address_to_str(wmem_packet_scope(), &pinfo->dst));

		netrom_tree = proto_item_add_subtree( ti, ett_netrom );

		offset = 0;

		/* source */
		proto_tree_add_item( netrom_tree, hf_netrom_src, tvb, offset, AX25_ADDR_LEN, ENC_NA );
		offset += AX25_ADDR_LEN;

		/* destination */
		proto_tree_add_item( netrom_tree, hf_netrom_dst, tvb, offset, AX25_ADDR_LEN, ENC_NA );
		offset += AX25_ADDR_LEN;

		/* ttl */
		proto_tree_add_item( netrom_tree, hf_netrom_ttl, tvb, offset, 1, ENC_BIG_ENDIAN );
		offset += 1;

		switch ( op_code )
			{
			case NETROM_PROTOEXT	:
						/* cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;
						break;
			case NETROM_CONNREQ	:
						/* cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;

						break;
			case NETROM_CONNACK	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* my cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* my cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						break;
			case NETROM_DISCREQ	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;

						break;
			case NETROM_DISCACK	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;

						break;
			case NETROM_INFO	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* n_s */
						proto_tree_add_item( netrom_tree, hf_netrom_n_s, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* n_r */
						proto_tree_add_item( netrom_tree, hf_netrom_n_r, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						break;
			case NETROM_INFOACK	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* n_r */
						proto_tree_add_item( netrom_tree, hf_netrom_n_r, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						break;
			default			:
						offset += 1;
						offset += 1;
						offset += 1;
						offset += 1;

						break;
			}

		/* type */
		dissect_netrom_type(	tvb,
					offset,
					pinfo,
					netrom_tree,
					hf_netrom_type,
					ett_netrom_type,
					&netrom_type_items
					);
		offset += 1;

		switch ( op_code )
			{
			case NETROM_PROTOEXT	:
						break;
			case NETROM_CONNREQ	:
						/* proposed window size */
						proto_tree_add_item( netrom_tree, hf_netrom_pwindow, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						proto_tree_add_item( netrom_tree, hf_netrom_user, tvb, offset, AX25_ADDR_LEN, ENC_NA );
						offset += AX25_ADDR_LEN;

						proto_tree_add_item( netrom_tree, hf_netrom_node, tvb, offset, AX25_ADDR_LEN, ENC_NA );
						offset += AX25_ADDR_LEN;

						break;
			case NETROM_CONNACK	:
						/* accepted window size */
						proto_tree_add_item( netrom_tree, hf_netrom_awindow, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						break;
			case NETROM_DISCREQ	:
						break;
			case NETROM_DISCACK	:
						break;
			case NETROM_INFO	:
						break;
			case NETROM_INFOACK	:
						break;
			default			:
						break;
			}
		}

	/* Call sub-dissectors here */

	next_tvb = tvb_new_subset_remaining(tvb, offset);

	switch ( op_code )
		{
		case NETROM_PROTOEXT	:
					if ( cct_index == NETROM_PROTO_IP && cct_id == NETROM_PROTO_IP )
						call_dissector( ip_handle , next_tvb, pinfo, tree );
					else
						call_dissector( data_handle , next_tvb, pinfo, tree );

					break;
		case NETROM_INFO	:
		default			:
					call_dissector( data_handle , next_tvb, pinfo, tree );
					break;
		}
}
Ejemplo n.º 6
0
/*
 * Dissect SNAP header; used elsewhere, e.g. in the Frame Relay dissector.
 */
void
dissect_snap(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
	     proto_tree *snap_tree, int control, int hf_oui, int hf_type, int hf_pid,
	     int bridge_pad)
{
	guint32		oui;
	guint16		etype;
	tvbuff_t	*next_tvb;
	oui_info_t	*oui_info;
	dissector_table_t subdissector_table;
	int		hf;
	int		mesh_header_len;

	/*
	 * XXX - what about non-UI frames?
	 */
	oui =	tvb_get_ntoh24(tvb, offset);
	etype = tvb_get_ntohs(tvb, offset+3);

	col_append_fstr(pinfo->cinfo, COL_INFO,
		    "; SNAP, OUI 0x%06X (%s), PID 0x%04X",
		    oui, val_to_str_const(oui, oui_vals, "Unknown"), etype);

	proto_tree_add_uint(snap_tree, hf_oui, tvb, offset, 3, oui);

	switch (oui) {

	case OUI_HP_2:
		oui_info = get_snap_oui_info(oui);
		hf = *oui_info->field_info->p_id;
		proto_tree_add_uint(snap_tree, hf, tvb, offset+3, 2, etype);
		next_tvb = tvb_new_subset_remaining(tvb, offset+5);

		if(!dissector_try_uint(hpteam_subdissector_table,etype, next_tvb, pinfo, tree))
	 		call_dissector(data_handle, next_tvb, pinfo, tree);
		break;

	case OUI_ENCAP_ETHER:
	case OUI_CISCO_90:
	case OUI_APPLE_ATALK:
		/* No, I have no idea why Apple used
		   one of their own OUIs, rather than
		   OUI_ENCAP_ETHER, and an Ethernet
		   packet type as protocol ID, for
		   AppleTalk data packets - but used
		   OUI_ENCAP_ETHER and an Ethernet
		   packet type for AARP packets. */
		if (XDLC_IS_INFORMATION(control)) {
			if (tree) {
				proto_tree_add_uint(snap_tree, hf_type,
				    tvb, offset+3, 2, etype);
			}
			next_tvb = tvb_new_subset_remaining(tvb, offset+5);
			if (!dissector_try_uint(ethertype_subdissector_table,
			    etype, next_tvb, pinfo, tree))
				call_dissector(data_handle, next_tvb, pinfo,
				    tree);
		} else {
			next_tvb = tvb_new_subset_remaining(tvb, offset+5);
			call_dissector(data_handle, next_tvb, pinfo, tree);
		}
		break;

	case OUI_IEEE_802_1:
		/*
		 * MAC frames bridged over ATM (RFC 2684) or Frame Relay
		 * (RFC 2427).
		 *
		 * We have to figure out how much padding to put
		 * into the frame.  We were handed a "bridge_pad"
		 * argument which should be 0 for Frame Relay and
		 * 2 for ATM; we add to that the amount of padding
		 * common to both bridging types.
		 */
		if (tree) {
			proto_tree_add_uint(snap_tree, hf_pid, tvb, offset+3, 2,
			    etype);
		}

		switch (etype) {

		case BPID_ETH_WITH_FCS:
			next_tvb = tvb_new_subset_remaining(tvb, offset+5+bridge_pad);
			call_dissector(eth_withfcs_handle, next_tvb, pinfo,
			    tree);
			break;

		case BPID_ETH_WITHOUT_FCS:
			next_tvb = tvb_new_subset_remaining(tvb, offset+5+bridge_pad);
			call_dissector(eth_withoutfcs_handle, next_tvb, pinfo, tree);
			break;

		case BPID_802_5_WITH_FCS:
		case BPID_802_5_WITHOUT_FCS:
			/*
			 * We treat the last padding byte as the Access
			 * Control byte, as that's what the Token
			 * Ring dissector expects the first byte to
			 * be.
			 */
			next_tvb = tvb_new_subset_remaining(tvb, offset+5+bridge_pad);
			call_dissector(tr_handle, next_tvb, pinfo, tree);
			break;

		case BPID_FDDI_WITH_FCS:
		case BPID_FDDI_WITHOUT_FCS:
			next_tvb = tvb_new_subset_remaining(tvb, offset+5+1+bridge_pad);
			call_dissector(fddi_handle, next_tvb, pinfo, tree);
			break;

		case BPID_BPDU:
			next_tvb = tvb_new_subset_remaining(tvb, offset+5);
			call_dissector(bpdu_handle, next_tvb, pinfo, tree);
			break;

		default:
			next_tvb = tvb_new_subset_remaining(tvb, offset+5);
			call_dissector(data_handle, next_tvb, pinfo, tree);
			break;
		}
		break;

	case OUI_CABLE_BPDU:    /* DOCSIS cable modem spanning tree BPDU */
		if (tree) {
			proto_tree_add_uint(snap_tree, hf_pid, tvb, offset+3, 2,
			    etype);
		}
		next_tvb = tvb_new_subset_remaining(tvb, offset+5);
		call_dissector(bpdu_handle, next_tvb, pinfo, tree);
		break;

	case OUI_TURBOCELL:
		next_tvb = tvb_new_subset_remaining(tvb, offset+3);
		call_dissector(turbo_handle, next_tvb, pinfo, tree);
		break;

	case OUI_MARVELL:
		/*
		 * OLPC packet.  The PID is an Ethertype, but
		 * there's a mesh header between the PID and
		 * the payload.
		 */
		if (XDLC_IS_INFORMATION(control)) {
			if (tree) {
				proto_tree_add_uint(snap_tree, hf_type,
				    tvb, offset+3, 2, etype);
			}
			next_tvb = tvb_new_subset_remaining(tvb, offset+5);
			mesh_header_len = call_dissector(mesh_handle,
			    next_tvb, pinfo, tree);
			next_tvb = tvb_new_subset_remaining(tvb, offset+5+mesh_header_len);
			if (!dissector_try_uint(ethertype_subdissector_table,
			    etype, next_tvb, pinfo, tree))
				call_dissector(data_handle, next_tvb, pinfo,
				    tree);
		} else {
			next_tvb = tvb_new_subset_remaining(tvb, offset+5);
			call_dissector(data_handle, next_tvb, pinfo, tree);
		}
		break;

	default:
		/*
		 * Do we have information for this OUI?
		 */
		oui_info = get_snap_oui_info(oui);
		if (oui_info != NULL) {
			/*
			 * Yes - use it.
			 */
			hf = *oui_info->field_info->p_id;
			subdissector_table = oui_info->table;
		} else {
			/*
			 * No, use hf_pid for the PID and just dissect
			 * the payload as data.
			 */
			hf = hf_pid;
			subdissector_table = NULL;
		}
		if (tree) {
			proto_tree_add_uint(snap_tree, hf, tvb, offset+3, 2,
			    etype);
		}
		next_tvb = tvb_new_subset_remaining(tvb, offset+5);
		if (XDLC_IS_INFORMATION(control)) {
			if (subdissector_table != NULL) {
				/* do lookup with the subdissector table */
				if (dissector_try_uint(subdissector_table,
				    etype, next_tvb, pinfo, tree))
					break;
			}
		}
		call_dissector(data_handle, next_tvb, pinfo, tree);
		break;
	}
}
Ejemplo n.º 7
0
/* Code to actually dissect the packets */
static void
dissect_ehdlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	int  offset = 4;

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

	while (tvb_reported_length_remaining(tvb, offset) > 0) {
		proto_item *ti            = NULL;
		proto_tree *ehdlc_tree    = NULL;
		guint16     len, msg_type;
		tvbuff_t   *next_tvb;
		guint16     control;
		gboolean    is_response   = FALSE, is_extended = TRUE;
		gint        header_length = 2; /* Address + Length field */

		msg_type      = tvb_get_guint8(tvb, offset);
		len           = tvb_get_guint8(tvb, offset+1);
#if 0
		col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",
		                val_to_str(msg_type, ehdlc_protocol_vals,
		                           "unknown 0x%02x"));
#endif
		if (tree) {
			/* Use MIN(...,...) in the following to prevent a premature */
			/* exception before we try to dissect whatever is available. */
			ti = proto_tree_add_protocol_format(tree, proto_ehdlc,
					tvb, offset, MIN(len, tvb_length_remaining(tvb,offset)),
					"Ericsson HDLC protocol, type: %s",
					val_to_str(msg_type, ehdlc_protocol_vals,
						   "unknown 0x%02x"));
			ehdlc_tree = proto_item_add_subtree(ti, ett_ehdlc);
			proto_tree_add_item(ehdlc_tree, hf_ehdlc_protocol,
					    tvb, offset, 1, ENC_BIG_ENDIAN);
#if 0
			proto_tree_add_item(ehdlc_tree, hf_ehdlc_sapi,
					    tvb, offset, 1, ENC_BIG_ENDIAN);
			proto_tree_add_item(ehdlc_tree, hf_ehdlc_c_r,
					    tvb, offset, 1, ENC_BIG_ENDIAN);
#endif
			proto_tree_add_item(ehdlc_tree, hf_ehdlc_data_len,
					    tvb, offset+1, 1, ENC_BIG_ENDIAN);
		}

		control = dissect_xdlc_control(tvb, offset+2, pinfo, ehdlc_tree, hf_ehdlc_control,
					       ett_ehdlc_control, &ehdlc_cf_items, &ehdlc_cf_items_ext,
					       NULL, NULL, is_response, is_extended, FALSE);
		header_length += XDLC_CONTROL_LEN(control, is_extended);

		if (XDLC_IS_INFORMATION(control)) {
			next_tvb = tvb_new_subset(tvb, offset+header_length,
						  len-header_length, len-header_length);

			switch (msg_type) {
			case 0x20:
				/* len == 4 seems to be some kind of ACK */
				if (len <= 4)
					break;
				call_dissector(sub_handles[SUB_RSL], next_tvb, pinfo, tree);
				break;
			case 0xbc:
			case 0xdc:
			case 0xa0:
			case 0xc0:
				/* len == 4 seems to be some kind of ACK */
				if (len <= 4)
					break;
				call_dissector(sub_handles[SUB_OML], next_tvb, pinfo, tree);
				break;
			default:
				call_dissector(sub_handles[SUB_DATA], next_tvb, pinfo, tree);
				break;
			}
		} else if (control == (XDLC_U | XDLC_XID)) {
			/* XID is formatted like ISO 8885, typically we see
 			 * something like
			 * 82		format identifier
			 * 80		group identifier
			 * 00 09 	length
			 * 07 01 05 	Window Size Tx
			 * 09 01 04	Ack Timer (msec)
			 * 08 01 05	Window Size Rx */
			proto_tree_add_item(ehdlc_tree, hf_ehdlc_xid_payload,
					    tvb, offset+header_length,
					    len-header_length, ENC_NA);
		}

		if (len == 0)
			len = 1;
		offset += len;
	}
}
Ejemplo n.º 8
0
static int
dissect_text_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
	proto_tree	*subtree;
	proto_item	*ti;
	gint		offset = 0, next_offset;
	gint		len;
	const char	*data_name;
	int length = tvb_length(tvb);

	/* Check if this is actually xml
	 * If there is less than 38 characters this is not XML
	 * <?xml version="1.0" encoding="UTF-8"?>
	 */
	if(length > 38){
		if (tvb_strncaseeql(tvb, 0, "<?xml", 5) == 0){
			call_dissector(xml_handle, tvb, pinfo, tree);
			return length;
		}
	}

	data_name = pinfo->match_string;
	if (! (data_name && data_name[0])) {
		/*
		 * No information from "match_string"
		 */
		data_name = (char *)data;
		if (! (data_name && data_name[0])) {
			/*
			 * No information from dissector data
			 */
			data_name = NULL;
		}
	}

	if (data_name)
		col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)",
				data_name);

	if (tree) {
		ti = proto_tree_add_item(tree, proto_text_lines,
				tvb, 0, -1, ENC_NA);
		if (data_name)
			proto_item_append_text(ti, ": %s", data_name);
		subtree = proto_item_add_subtree(ti, ett_text_lines);
		/* Read the media line by line */
		while (tvb_offset_exists(tvb, offset)) {
			/*
			 * XXX - we need to be passed the parameters
			 * of the content type via data parameter,
			 * so that we know the character set.  We'd
			 * have to handle that character set, which
			 * might be a multibyte character set such
			 * as "iso-10646-ucs-2", or might require other
			 * special processing.
			 */
			len = tvb_find_line_end(tvb, offset,
					tvb_ensure_length_remaining(tvb, offset),
					&next_offset, FALSE);
			if (len == -1)
				break;

			/* We use next_offset - offset instead of len in the
			 * call to proto_tree_add_format_text() so it will include the
			 * line terminator(s) (\r and/or \n) in the display.
			 */
			proto_tree_add_format_text(subtree, tvb, offset, next_offset - offset);
			offset = next_offset;
		}
	}

	return length;
}
Ejemplo n.º 9
0
static gboolean
dissect_fcip (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
              gboolean check_port)
{
    gint offset = 0,
         start  = 0,
         frame_len = 0;
    gint bytes_remaining = tvb_length (tvb);
    guint8 pflags, sof = 0, eof = 0;
   /* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti;
    proto_tree *fcip_tree = NULL;
    tvbuff_t *next_tvb;
    fc_data_t fc_data;

    if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) {
        return FALSE;
    }

    if (check_port &&
        ((pinfo->srcport != fcip_port) && (pinfo->destport != fcip_port))) {
        return FALSE;
    }

    while (bytes_remaining > FCIP_ENCAP_HEADER_LEN) {
        if ((offset = get_next_fcip_header_offset (tvb, pinfo, offset)) == -1) {
            return FALSE;
        }
        else if (offset == -2) {
            /* We need more data to desegment */
            return (TRUE);
        }

        start = offset;
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCIP");

        frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4;

        if (bytes_remaining < frame_len) {
            if(fcip_desegment && pinfo->can_desegment) {
                /*
                 * This frame doesn't have all of the data for
                 * this message, but we can do reassembly on it.
                 *
                 * Tell the TCP dissector where the data for this
                 * message starts in the data it handed us, and
                 * how many more bytes we need, and return.
                 */
                pinfo->desegment_offset = offset;
                pinfo->desegment_len = frame_len - bytes_remaining;
                return (TRUE);
            }
        }

        pflags = tvb_get_guint8 (tvb, start+8);

        if (tree) {
            if (FCIP_IS_SF (pflags)) {
                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP");
            }
            else if (tvb_bytes_exist (tvb, offset, offset+frame_len-4)) {
                sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);
                eof = tvb_get_guint8 (tvb, offset+frame_len - 4);

                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP (%s/%s)",
                                                     val_to_str (sof, fcip_sof_vals,
                                                                 "0x%x"),
                                                     val_to_str (eof, fcip_eof_vals,
                                                                 "0x%x"));
            }
            else {
                sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);

                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP (%s/%s)",
                                                     val_to_str (sof, fcip_sof_vals,
                                                                 "0x%x"),
                                                     "NA");
            }
            fcip_tree = proto_item_add_subtree (ti, ett_fcip);
            /* Dissect the Common FC Encap header */
            dissect_fcencap_header (tvb, fcip_tree, offset);

            offset += FCIP_ENCAP_HEADER_LEN;

            if (!FCIP_IS_SF (pflags)) {
                /* print SOF */
                proto_tree_add_item (fcip_tree, hf_fcip_sof, tvb, offset, 1, ENC_BIG_ENDIAN);
                proto_tree_add_item (fcip_tree, hf_fcip_sof_c, tvb, offset+2, 1, ENC_BIG_ENDIAN);
                /* print EOF */

                offset += (frame_len-FCIP_ENCAP_HEADER_LEN-4);
                if (tvb_bytes_exist (tvb, offset, 4)) {
                    proto_tree_add_item (fcip_tree, hf_fcip_eof, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item (fcip_tree, hf_fcip_eof_c, tvb, offset+2, 1, ENC_BIG_ENDIAN);
                }
            }
        }

        /* Call the FC Dissector if this is carrying an FC frame */
        if (!FCIP_IS_SF(pflags)) {
            /* Set the SOF/EOF flags in the packet_info header */
            fc_data.sof_eof = 0;

            if (sof) {
                if ((sof == FCIP_SOFi3) || (sof == FCIP_SOFi2) || (sof == FCIP_SOFi4)) {
                    fc_data.sof_eof = FC_DATA_SOF_FIRST_FRAME;
                }
                else if (sof == FCIP_SOFf) {
                    fc_data.sof_eof = FC_DATA_SOF_SOFF;
                }

                if (eof != FCIP_EOFn) {
                    fc_data.sof_eof |= FC_DATA_EOF_LAST_FRAME;
                }
                else if (eof != FCIP_EOFt) {
                    fc_data.sof_eof |= FC_DATA_EOF_INVALID;
                }
            }

            /* Special frame bit is not set */
            next_tvb = tvb_new_subset_remaining (tvb, FCIP_ENCAP_HEADER_LEN+4);
            if (fc_handle) {
                fc_data.ethertype = 0;
                call_dissector_with_data(fc_handle, next_tvb, pinfo, tree, &fc_data);
            }
            else if (data_handle) {
                call_dissector (data_handle, next_tvb, pinfo, tree);
            }
        }
        else {
            col_set_str(pinfo->cinfo, COL_INFO, "Special Frame");
            if (FCIP_IS_CH (pflags)) {
                col_append_str(pinfo->cinfo, COL_INFO, "(Changed)");
            }

            dissect_fcip_sf (tvb, fcip_tree, offset+4);
        }

        bytes_remaining -= frame_len;
    }

    return (TRUE);
}
Ejemplo n.º 10
0
/* Code to actually dissect the packets */
static void
dissect_sm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item *ti;
	proto_tree *sm_tree;
	tvbuff_t *next_tvb = NULL;
	guint32 sm_message_type;
	guint16 protocol;
	guint16 msg_type = 0;
	guint16 length;
	guint16 tag;
	int     offset = 0;

	sm_message_type = tvb_get_ntohl(tvb,offset);

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "SM");

	col_add_fstr(pinfo->cinfo, COL_INFO, "Cisco SM Packet (%s)",
		val_to_str(sm_message_type, sm_message_type_value_info,"reserved"));

	ti = proto_tree_add_item(tree, proto_sm, tvb, offset, 0, ENC_NA);
	sm_tree = proto_item_add_subtree(ti, ett_sm);

	proto_tree_add_uint_format(sm_tree, hf_sm_sm_msg_type, tvb, offset, 4, sm_message_type,
		"SM Message type: %s (0x%0x)", val_to_str(sm_message_type, sm_message_type_value, "reserved"), sm_message_type);

	offset = offset + 4;
	if (sm_message_type ==  MESSAGE_TYPE_PDU) {
		proto_tree_add_item(sm_tree, hf_sm_protocol, tvb, offset, 2, ENC_BIG_ENDIAN);
		protocol = tvb_get_ntohs(tvb,offset);
		offset = offset + 2;
		switch(protocol){
		case SM_PROTOCOL_X100:
		case SM_PROTOCOL_X122:
			if (!tree)
				return;
			/* Protocol 0x100/0x122 only contains a length and then an EISUP packet */
			proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN);
			length = tvb_get_ntohs(tvb,offset);
			offset = offset + 2;
			proto_item_set_len(ti, 8);

			/* This should be the EISUP dissector but we havent got one
			 * right now - so decode it as data for now ... */
			next_tvb = tvb_new_subset(tvb, offset, length, length);
			call_dissector(data_handle, next_tvb, pinfo, sm_tree);

			break;
		case SM_PROTOCOL_X101:
			if (!tree)
				return;
			/* XXX Reveres enginered so this may not be correct!!!
			 * EISUP - used between Cisco HSI and Cisco PGW devices,
			 * uses RUDP with default port number 8003.
			 * Protocol stack is RUDP->Cisco SM->SDP.
			 * This implementation is PROPRIETARY
			 */
			proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN);
			length = tvb_get_ntohs(tvb,offset);
			offset = offset + 2;
			proto_item_set_len(ti, length + offset);
			/* The next stuff seems to be IP addr */
			proto_tree_add_item(sm_tree, hf_sm_ip_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
			offset = offset + 4;
			/* This part looks to be the same per session */
			proto_tree_add_item(sm_tree, hf_sm_context, tvb, offset, 4, ENC_BIG_ENDIAN);
			offset = offset +4;
			/* Some sort of message type? */
			proto_tree_add_item(sm_tree, hf_sm_eisup_msg_id, tvb, offset, 1, ENC_BIG_ENDIAN);
			offset = offset + 1;
			/* XXX Problem are tags 1 or two bytes???*/
			proto_tree_add_item(sm_tree, hf_sm_tag, tvb, offset, 2, ENC_BIG_ENDIAN);

			tag = tvb_get_ntohs(tvb,offset);
			offset = offset +2;
			if (tag== 0x01ac) {
				proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN);
				length = tvb_get_ntohs(tvb,offset);
				offset = offset +2;
				next_tvb = tvb_new_subset(tvb, offset, length, length);
				call_dissector(sdp_handle, next_tvb, pinfo, sm_tree);
				offset = offset+length;

			}
			/*return;*/
			break;
		case SM_PROTOCOL_X114:
			if (!tree)
				return;
			/* XXX Reveres enginered so this may not be correct!!! */
			proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN);
			length = tvb_get_ntohs(tvb,offset);
			offset = offset + 2;
			proto_item_set_len(ti, length + offset);
			/* The next stuff seems to be IP addr */
			proto_tree_add_item(sm_tree, hf_sm_ip_addr, tvb, offset, 4, ENC_BIG_ENDIAN);
			offset = offset + 4;
			proto_tree_add_item(sm_tree, hf_sm_context, tvb, offset, 4, ENC_BIG_ENDIAN);
			offset = offset +4;
			/* Some sort of message type? */
			proto_tree_add_item(sm_tree, hf_sm_eisup_msg_id, tvb, offset, 1, ENC_BIG_ENDIAN);
			offset = offset + 1;
			/* XXX Problem are tags 1 or two bytes???*/
			proto_tree_add_item(sm_tree, hf_sm_tag, tvb, offset, 2, ENC_BIG_ENDIAN);

			tag = tvb_get_ntohs(tvb,offset);
			offset = offset +2;
			if (tag== 0x01ac) {
				proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN);
				length = tvb_get_ntohs(tvb,offset);
				offset = offset +2;
				next_tvb = tvb_new_subset(tvb, offset, length, length);
				call_dissector(sdp_handle, next_tvb, pinfo, sm_tree);
				offset = offset+length;

			}
			break;
		default:
			proto_tree_add_item(sm_tree, hf_sm_msg_id, tvb, offset, 2, ENC_BIG_ENDIAN);
			offset = offset +2;
			msg_type = tvb_get_ntohs(tvb,offset);
			proto_tree_add_uint_format(sm_tree, hf_sm_msg_type, tvb, offset, 2, msg_type,
				"Message type: %s (0x%0x)", val_to_str(msg_type, sm_pdu_type_value, "reserved"),
				msg_type);
			msg_type = tvb_get_ntohs(tvb,offset);
			offset = offset + 2;
			proto_tree_add_item(sm_tree, hf_sm_channel, tvb, offset, 2, ENC_BIG_ENDIAN);
			offset = offset + 2;
			proto_tree_add_item(sm_tree, hf_sm_bearer, tvb, offset, 2, ENC_BIG_ENDIAN);
			offset = offset +2;
			proto_tree_add_item(sm_tree, hf_sm_len, tvb, offset, 2, ENC_BIG_ENDIAN);
			length = tvb_get_ntohs(tvb,offset);
			offset = offset +2;
			proto_item_set_len(ti, 16);

			if (length > 0) {
				next_tvb = tvb_new_subset(tvb, offset, length, length);

				if ((msg_type == PDU_MTP3_TO_SLT || msg_type == PDU_MTP3_FROM_SLT)) {
					call_dissector(mtp3_handle, next_tvb, pinfo, tree);
				} else {
					call_dissector(data_handle, next_tvb, pinfo, tree);
				}
			}
		}
	}

}
Ejemplo n.º 11
0
/*
 * XXX - do reassembly, using the EOM flag.  (Then do that in the Netware
 * SPX implementation, too.)
 *
 * XXX - hand off to subdissectors based on the socket number.
 */
static void
dissect_spp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*spp_tree = NULL;
	proto_item	*ti;
	tvbuff_t	*next_tvb;
	guint8		conn_ctrl;
	proto_tree	*cc_tree;
	guint8		datastream_type;
	const char	*datastream_type_string;
	guint16         spp_seq;
	const char	*spp_msg_string;
	guint16		low_socket, high_socket;

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

	if (tree) {
		ti = proto_tree_add_item(tree, proto_spp, tvb, 0, SPP_HEADER_LEN, ENC_NA);
		spp_tree = proto_item_add_subtree(ti, ett_spp);
	}

	conn_ctrl = tvb_get_guint8(tvb, 0);
	spp_msg_string = spp_conn_ctrl(conn_ctrl);
	if (check_col(pinfo->cinfo, COL_INFO))
		col_append_fstr(pinfo->cinfo, COL_INFO, " %s", spp_msg_string);
	if (tree) {
		ti = proto_tree_add_uint_format(spp_tree, hf_spp_connection_control, tvb,
						0, 1, conn_ctrl,
						"Connection Control: %s (0x%02X)",
						spp_msg_string, conn_ctrl);
		cc_tree = proto_item_add_subtree(ti, ett_spp_connctrl);
		proto_tree_add_boolean(cc_tree, hf_spp_connection_control_sys, tvb,
				       0, 1, conn_ctrl);
		proto_tree_add_boolean(cc_tree, hf_spp_connection_control_send_ack, tvb,
				       0, 1, conn_ctrl);
		proto_tree_add_boolean(cc_tree, hf_spp_connection_control_attn, tvb,
				       0, 1, conn_ctrl);
		proto_tree_add_boolean(cc_tree, hf_spp_connection_control_eom, tvb,
				       0, 1, conn_ctrl);
	}

	datastream_type = tvb_get_guint8(tvb, 1);
	datastream_type_string = spp_datastream(datastream_type);
	if (datastream_type_string != NULL) {
		if (check_col(pinfo->cinfo, COL_INFO))
			col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
			    datastream_type_string);
	}
	if (tree) {
		if (datastream_type_string != NULL) {
			proto_tree_add_uint_format(spp_tree, hf_spp_datastream_type, tvb,
						   1, 1, datastream_type,
						   "Datastream Type: %s (0x%02X)",
						   datastream_type_string,
						   datastream_type);
		} else {
			proto_tree_add_uint_format(spp_tree, hf_spp_datastream_type, tvb,
						   1, 1, datastream_type,
						   "Datastream Type: 0x%02X",
						   datastream_type);
		}
		proto_tree_add_item(spp_tree, hf_spp_src_id, tvb,  2, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(spp_tree, hf_spp_dst_id, tvb,  4, 2, ENC_BIG_ENDIAN);
	}
	spp_seq = tvb_get_ntohs(tvb, 6);
	if (tree) {
		proto_tree_add_uint(spp_tree, hf_spp_seq_nr, tvb,  6, 2, spp_seq);
		proto_tree_add_item(spp_tree, hf_spp_ack_nr, tvb,  8, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(spp_tree, hf_spp_all_nr, tvb, 10, 2, ENC_BIG_ENDIAN);
	}

	if (tvb_reported_length_remaining(tvb, SPP_HEADER_LEN) > 0) {
		if (pinfo->srcport > pinfo->destport) {
			low_socket = pinfo->destport;
			high_socket = pinfo->srcport;
		} else {
			low_socket = pinfo->srcport;
			high_socket = pinfo->destport;
		}

		next_tvb = tvb_new_subset_remaining(tvb, SPP_HEADER_LEN);
		if (dissector_try_uint(spp_socket_dissector_table, low_socket,
		    next_tvb, pinfo, tree))
			return;
		if (dissector_try_uint(spp_socket_dissector_table, high_socket,
		    next_tvb, pinfo, tree))
			return;
		call_dissector(data_handle, next_tvb, pinfo, tree);
	}
}
Ejemplo n.º 12
0
static int
dissect_data_segment(proto_tree *ltp_tree, tvbuff_t *tvb,packet_info *pinfo,int frame_offset,int ltp_type, guint64 session_num){
	guint64 client_id;
	guint64 offset;
	guint64 length;
	guint64 chkp_sno = 0;
	guint64 rpt_sno = 0;

	int segment_offset = 0;

	int client_id_size;
	int offset_size;
	int length_size;
	int chkp_sno_size;
	int rpt_sno_size;

	int data_offset = 0;
	int data_length;
	int bundle_size = 0;
	int dissected_data_size = 0;
	int data_count = 1;

	proto_tree *ltp_data_tree;
	proto_tree *ltp_data_data_tree;

	tvbuff_t *datatvb;

	fragment_head *frag_msg = NULL;
	gboolean more_frags = TRUE;

	tvbuff_t *new_tvb = NULL;

	/* Extract the info for the data segment */
	client_id = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&client_id_size);
	segment_offset+= client_id_size;

	if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){
	/* This would mean the data segment is incomplete */
		return 0;
	}
	offset = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&offset_size);
	segment_offset+= offset_size;

	if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){
	/* This would mean the data segment is incomplete */
		return 0;
	}

	length = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&length_size);
	segment_offset+= length_size;

	if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){
	/* This would mean the data segment is incomplete */
		return 0;
	}

	if(ltp_type != 0 )
	{
		chkp_sno = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&chkp_sno_size);
		segment_offset+= chkp_sno_size;

		if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){
		/* This would mean the data segment is incomplete */
			return 0;
		}

		rpt_sno = evaluate_sdnv_64(tvb,frame_offset + segment_offset,&rpt_sno_size);
		segment_offset+= rpt_sno_size;

		if((unsigned)(frame_offset + segment_offset) >= tvb_captured_length(tvb)){
		/* This would mean the data segment is incomplete */
			return 0;
		}
	}
	/* Adding size of the data */
	if ((segment_offset + (int)length < segment_offset) || (segment_offset + (int)length < (int)length)) {
	/* Addition result has wrapped */
		return 0;
	}
	segment_offset+= (int)length;

	if ((segment_offset + frame_offset < segment_offset) || (segment_offset + frame_offset < frame_offset)) {
	/* Addition result has wrapped */
		return 0;
	}
	if((unsigned)(frame_offset + segment_offset) > tvb_captured_length(tvb)){
	/* This would mean the data segment is incomplete */
		return 0;
	}

	/* Create a subtree for data segment and add the other fields under it */
	ltp_data_tree = proto_tree_add_subtree(ltp_tree, tvb,frame_offset, segment_offset, ett_data_segm, NULL, "Data Segment");

	proto_tree_add_uint64(ltp_data_tree,hf_ltp_data_clid, tvb, frame_offset,client_id_size,client_id);
	frame_offset += client_id_size;

	proto_tree_add_uint64(ltp_data_tree, hf_ltp_data_offset, tvb, frame_offset,offset_size, offset);
	frame_offset += offset_size;

	proto_tree_add_uint64(ltp_data_tree,hf_ltp_data_length, tvb, frame_offset,length_size,length);
	frame_offset += length_size;

	if(ltp_type != 0 )
	{
		proto_tree_add_uint64(ltp_data_tree, hf_ltp_data_chkp, tvb, frame_offset,chkp_sno_size, chkp_sno);
		frame_offset += chkp_sno_size;

		proto_tree_add_uint64(ltp_data_tree, hf_ltp_data_rpt, tvb, frame_offset,rpt_sno_size, rpt_sno);
		frame_offset += rpt_sno_size;

		more_frags = FALSE;
		frag_msg = fragment_add_check(&ltp_reassembly_table,
			  tvb, frame_offset, pinfo, (guint32)session_num, NULL,
			  (guint32)offset, (guint32)length, more_frags);
	}
	else
	{
		more_frags = TRUE;
		frag_msg = fragment_add_check(&ltp_reassembly_table,
			 tvb, frame_offset, pinfo, (guint32)session_num, NULL,
			 (guint32)offset, (guint32)length, more_frags);

	}


	if(frag_msg)
	{
		/* Checking if the segment is completely reassembled */
		if(!(frag_msg->flags & FD_PARTIAL_REASSEMBLY))
		{
			/* if the segment has not been fragmented, then no reassembly is needed */
			if(!more_frags && offset == 0)
			{
				new_tvb = tvb_new_subset_remaining(tvb,frame_offset);
			}
			else
			{
				new_tvb = process_reassembled_data(tvb, frame_offset, pinfo, "Reassembled LTP Segment",
					frag_msg, &ltp_frag_items,NULL, ltp_data_tree);

			}
		}
	}

	if(new_tvb)
	{
		data_length = tvb_captured_length(new_tvb);
		while(dissected_data_size < data_length)
		{
			ltp_data_data_tree = proto_tree_add_subtree_format(ltp_data_tree, tvb,frame_offset, 0,
												ett_data_data_segm, NULL, "Data[%d]",data_count);

			datatvb = tvb_new_subset(new_tvb, data_offset, (int)data_length - dissected_data_size, tvb_captured_length(new_tvb));
			bundle_size = call_dissector(bundle_handle, datatvb, pinfo, ltp_data_data_tree);
			if(bundle_size == 0) {  /*Couldn't parse bundle*/
				col_set_str(pinfo->cinfo, COL_INFO, "Dissection Failed");
				return 0;           /*Give up*/
			}
			data_offset += bundle_size;
			dissected_data_size += bundle_size;
			data_count++;
		}
	}
	else
	{
		if(frag_msg && more_frags)
		{
			col_append_fstr(pinfo->cinfo, COL_INFO, "[Reassembled in %d] ",frag_msg->reassembled_in);
		}
		else
		{
			col_append_str(pinfo->cinfo, COL_INFO, "[Unfinished LTP Segment] ");
		}

	}

	return segment_offset;
}
Ejemplo n.º 13
0
/* *** Code to actually dissect the packets *** */
static int dissect_dvb_s2_gse(tvbuff_t *tvb, int cur_off, proto_tree *tree, packet_info *pinfo)
{
    int         new_off                      = 0;
    int         frag_len;
    guint16     gse_hdr, data_len, gse_proto = 0;

    proto_item *ti, *tf;
    proto_tree *dvb_s2_gse_tree, *dvb_s2_gse_hdr_tree;

    tvbuff_t   *next_tvb;

    col_append_str(pinfo->cinfo, COL_INFO, "GSE");

    /* get header and determine length */
    gse_hdr = tvb_get_ntohs(tvb, cur_off + DVB_S2_GSE_OFFS_HDR);
    new_off += 2;
    frag_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK)+2;

    ti = proto_tree_add_item(tree, proto_dvb_s2_gse, tvb, cur_off, frag_len, ENC_NA);
    dvb_s2_gse_tree = proto_item_add_subtree(ti, ett_dvb_s2_gse);

    tf = proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_hdr, tvb, cur_off + DVB_S2_GSE_OFFS_HDR, 2, gse_hdr);

    dvb_s2_gse_hdr_tree = proto_item_add_subtree(tf, ett_dvb_s2_gse_hdr);
    proto_tree_add_item(dvb_s2_gse_hdr_tree, hf_dvb_s2_gse_hdr_start, tvb, cur_off + DVB_S2_GSE_OFFS_HDR, 2, ENC_BIG_ENDIAN);
    proto_tree_add_item(dvb_s2_gse_hdr_tree, hf_dvb_s2_gse_hdr_stop, tvb, cur_off + DVB_S2_GSE_OFFS_HDR, 2, ENC_BIG_ENDIAN);
    proto_tree_add_item(dvb_s2_gse_hdr_tree, hf_dvb_s2_gse_hdr_labeltype, tvb,
                        cur_off + DVB_S2_GSE_OFFS_HDR, 2, ENC_BIG_ENDIAN);
    proto_tree_add_item(dvb_s2_gse_hdr_tree, hf_dvb_s2_gse_hdr_length, tvb, cur_off + DVB_S2_GSE_OFFS_HDR, 2, ENC_BIG_ENDIAN);

    if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) &&
            BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS) &&
            BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) {
        col_append_str(pinfo->cinfo, COL_INFO, " ");
        return new_off;
    } else {
        if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) || BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {

            proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_fragid, tvb, cur_off + new_off, 1, ENC_BIG_ENDIAN);

            new_off += 1;
        }
        if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {

            proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_totlength, tvb, cur_off + new_off, 2, ENC_BIG_ENDIAN);
            col_append_str(pinfo->cinfo, COL_INFO, "(frag) ");

            new_off += 2;
        }
        if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS)) {
            gse_proto = tvb_get_ntohs(tvb, cur_off + new_off);

            proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_proto, tvb, cur_off + new_off, 2, ENC_BIG_ENDIAN);

            new_off += 2;

            if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) {
                /* 6 byte label */
                if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS))
                    col_append_str(pinfo->cinfo, COL_INFO, "6 ");

                proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_label6, tvb, cur_off + new_off, 6, ENC_NA);

                new_off += 6;
            } else if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) &&
                       BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) {
                /* 3 byte label */
                if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS))
                    col_append_str(pinfo->cinfo, COL_INFO, "3 ");

                proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_label3, tvb, cur_off + new_off, 3, ENC_NA);

                new_off += 3;
            } else {
                /* 0 byte label */
                if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS))
                    col_append_str(pinfo->cinfo, COL_INFO, "0 ");
            }
            if (gse_proto < 0x0600 && gse_proto >= 0x100) {
                /* Only display optional extension headers */
                /* TODO: needs to be tested */

                /* TODO: implementation needs to be checked (len of ext-header??) */
                proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_exthdr, tvb, cur_off + new_off, 1, ENC_BIG_ENDIAN);

                new_off += 1;
            }
        }
        else
        {
            /* correct cinfo */
            col_append_str(pinfo->cinfo, COL_INFO, "(frag) ");
        }

        next_tvb = tvb_new_subset_remaining(tvb, cur_off + new_off);

        if (dvb_s2_full_dissection)
        {
            switch (gse_proto) {
            case ETHERTYPE_IP:
                new_off += call_dissector(ip_handle, next_tvb, pinfo, tree);
                break;
            case ETHERTYPE_IPv6:
                new_off += call_dissector(ipv6_handle, next_tvb, pinfo, tree);
                break;
            default:
                if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {
                    data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN;
                } else
                    data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE);

                proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA);
                new_off += data_len;
                break;
            }
        }
        else
        {
            if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {
                data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN;
            } else
                data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE);

            proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA);
            new_off += data_len;
        }

        /* add crc32 if last fragment */
        if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {
            proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_crc32, tvb, cur_off + new_off, DVB_S2_GSE_CRC32_LEN, ENC_NA);
            new_off += DVB_S2_GSE_CRC32_LEN;
        }
    }

    return new_off;
}
Ejemplo n.º 14
0
static void
dissect_file_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
	proto_item  *volatile ti = NULL;
	guint	     cap_len = 0, frame_len = 0;
	proto_tree  *volatile tree;
	proto_item  *item;
	const gchar *cap_plurality, *frame_plurality;

	tree=parent_tree;

	pinfo->current_proto = "File";

	/* if FILE is not referenced from any filters we don't need to worry about
	   generating any tree items.  */
	if(!proto_field_is_referenced(tree, proto_file)) {
		tree=NULL;
	} else {
		proto_tree *fh_tree;
		gboolean old_visible;

		/* Put in frame header information. */
		cap_len = tvb_length(tvb);
		frame_len = tvb_reported_length(tvb);

		cap_plurality = plurality(cap_len, "", "s");
		frame_plurality = plurality(frame_len, "", "s");

		ti = proto_tree_add_protocol_format(tree, proto_file, tvb, 0, -1,
		    "File record %u: %u byte%s",
		    pinfo->fd->num, frame_len, frame_plurality);
		proto_item_append_text(ti, ", %u byte%s",
		    cap_len, cap_plurality);

		fh_tree = proto_item_add_subtree(ti, ett_file);

		proto_tree_add_int(fh_tree, hf_file_ftap_encap, tvb, 0, 0, pinfo->fd->lnk_t);

		proto_tree_add_uint(fh_tree, hf_file_record_number, tvb, 0, 0, pinfo->fd->num);

		proto_tree_add_uint_format(fh_tree, hf_file_record_len, tvb,
					   0, 0, frame_len, "Record Length: %u byte%s (%u bits)",
					   frame_len, frame_plurality, frame_len * 8);

		ti = proto_tree_add_boolean(fh_tree, hf_file_marked, tvb, 0, 0,pinfo->fd->flags.marked);
		PROTO_ITEM_SET_GENERATED(ti);

		ti = proto_tree_add_boolean(fh_tree, hf_file_ignored, tvb, 0, 0,pinfo->fd->flags.ignored);
		PROTO_ITEM_SET_GENERATED(ti);

		if(proto_field_is_referenced(tree, hf_file_protocols)) {
			/* we are going to be using proto_item_append_string() on
			 * hf_frame_protocols, and we must therefore disable the
			 * TRY_TO_FAKE_THIS_ITEM() optimisation for the tree by
			 * setting it as visible.
			 *
			 * See proto.h for details.
			 */
			old_visible = proto_tree_set_visible(fh_tree, TRUE);
			ti = proto_tree_add_string(fh_tree, hf_file_protocols, tvb, 0, 0, "");
			PROTO_ITEM_SET_GENERATED(ti);
			proto_tree_set_visible(fh_tree, old_visible);
		}

		if(pinfo->fd->pfd != 0){
			proto_item *ppd_item;
			guint num_entries = g_slist_length(pinfo->fd->pfd);
			guint i;
			ppd_item = proto_tree_add_uint(fh_tree, hf_file_num_p_prot_data, tvb, 0, 0, num_entries);
			PROTO_ITEM_SET_GENERATED(ppd_item);
			for(i=0; i<num_entries; i++){
				proto_tree_add_text (fh_tree, tvb, 0, 0, "%s",p_get_proto_name_and_key(wmem_file_scope(), pinfo, i));
			}
		}

#if 0
		if (show_file_off) {
			proto_tree_add_int64_format_value(fh_tree, hf_frame_file_off, tvb,
						    0, 0, pinfo->fd->file_off,
						    "%" G_GINT64_MODIFIER "d (0x%" G_GINT64_MODIFIER "x)",
						    pinfo->fd->file_off, pinfo->fd->file_off);
		}
#endif

		if(pinfo->fd->color_filter != NULL) {
			const color_filter_t *color_filter = (const color_filter_t *)pinfo->fd->color_filter;
			item = proto_tree_add_string(fh_tree, hf_file_color_filter_name, tvb,
						     0, 0, color_filter->filter_name);
			PROTO_ITEM_SET_GENERATED(item);
			item = proto_tree_add_string(fh_tree, hf_file_color_filter_text, tvb,
						     0, 0, color_filter->filter_text);
			PROTO_ITEM_SET_GENERATED(item);
		}
	}

	if (pinfo->fd->flags.ignored) {
		/* Ignored package, stop handling here */
		col_set_str(pinfo->cinfo, COL_INFO, "<Ignored>");
		proto_tree_add_text (tree, tvb, 0, -1, "This record is marked as ignored");
		return;
	}

	/* Portable Exception Handling to trap Wireshark specific exceptions like BoundsError exceptions */
	TRY {
#ifdef _MSC_VER
		/* Win32: Visual-C Structured Exception Handling (SEH) to trap hardware exceptions
		   like memory access violations.
		   (a running debugger will be called before the except part below) */
                /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling)
                   stack in an inconsistent state thus causing a crash at some point in the
                   handling of the exception.
                   See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html
                */
		__try {
#endif
			if (!dissector_try_uint(file_encap_dissector_table, pinfo->fd->lnk_t,
						tvb, pinfo, parent_tree)) {

				col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
				col_add_fstr(pinfo->cinfo, COL_INFO, "FTAP_ENCAP = %d",
					     pinfo->fd->lnk_t);
				call_dissector(data_handle,tvb, pinfo, parent_tree);
			}
#ifdef _MSC_VER
		} __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) {
			switch(GetExceptionCode()) {
			case(STATUS_ACCESS_VIOLATION):
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address");
				break;
			case(STATUS_INTEGER_DIVIDE_BY_ZERO):
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero");
				break;
			case(STATUS_STACK_OVERFLOW):
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)");
				/* XXX - this will have probably corrupted the stack,
				   which makes problems later in the exception code */
				break;
				/* XXX - add other hardware exception codes as required */
			default:
				show_exception(tvb, pinfo, parent_tree, DissectorError,
					       g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode()));
			}
		}
#endif
	}
	CATCH_BOUNDS_AND_DISSECTOR_ERRORS {
		show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
	}
	ENDTRY;

    if(proto_field_is_referenced(tree, hf_file_protocols)) {
		wmem_strbuf_t *val = wmem_strbuf_new(wmem_packet_scope(), "");
		wmem_list_frame_t *frame;
		/* skip the first entry, it's always the "frame" protocol */
		frame = wmem_list_frame_next(wmem_list_head(pinfo->layers));
		if (frame) {
			wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame))));
			frame = wmem_list_frame_next(frame);
		}
		while (frame) {
			wmem_strbuf_append_c(val, ':');
			wmem_strbuf_append(val, proto_get_protocol_filter_name(GPOINTER_TO_UINT(wmem_list_frame_data(frame))));
			frame = wmem_list_frame_next(frame);
		}
		proto_item_append_string(ti, wmem_strbuf_get_str(val));
	}

	/*  Call postdissectors if we have any (while trying to avoid another
	 *  TRY/CATCH)
	 */
	if (have_postdissector()) {
		TRY {
#ifdef _MSC_VER
			/* Win32: Visual-C Structured Exception Handling (SEH)
			   to trap hardware exceptions like memory access violations */
			/* (a running debugger will be called before the except part below) */
                        /* Note: A Windows "exceptional exception" may leave the kazlib's (Portable Exception Handling)
                           stack in an inconsistent state thus causing a crash at some point in the
                           handling of the exception.
                           See: https://www.wireshark.org/lists/wireshark-dev/200704/msg00243.html
                        */
			__try {
#endif
				call_all_postdissectors(tvb, pinfo, parent_tree);
#ifdef _MSC_VER
			} __except(EXCEPTION_EXECUTE_HANDLER /* handle all exceptions */) {
				switch(GetExceptionCode()) {
				case(STATUS_ACCESS_VIOLATION):
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       "STATUS_ACCESS_VIOLATION: dissector accessed an invalid memory address");
					break;
				case(STATUS_INTEGER_DIVIDE_BY_ZERO):
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       "STATUS_INTEGER_DIVIDE_BY_ZERO: dissector tried an integer division by zero");
					break;
				case(STATUS_STACK_OVERFLOW):
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       "STATUS_STACK_OVERFLOW: dissector overflowed the stack (e.g. endless loop)");
					/* XXX - this will have probably corrupted the stack,
					   which makes problems later in the exception code */
					break;
					/* XXX - add other hardware exception codes as required */
				default:
					show_exception(tvb, pinfo, parent_tree, DissectorError,
						       g_strdup_printf("dissector caused an unknown exception: 0x%x", GetExceptionCode()));
				}
			}
#endif
		}
		CATCH_BOUNDS_AND_DISSECTOR_ERRORS {
			show_exception(tvb, pinfo, parent_tree, EXCEPT_CODE, GET_MESSAGE);
		}
		ENDTRY;
	}

	tap_queue_packet(file_tap, pinfo, NULL);


	if (pinfo->frame_end_routines) {
		g_slist_foreach(pinfo->frame_end_routines, &call_file_record_end_routine, NULL);
		g_slist_free(pinfo->frame_end_routines);
		pinfo->frame_end_routines = NULL;
	}
}
Ejemplo n.º 15
0
/* Code to actually dissect the packets */
static void
dissect_mdshdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

/* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti_main, *ti_hdr, *ti_trlr;
    proto_item *hidden_item; 
    proto_tree *mdshdr_tree_main, *mdshdr_tree_hdr, *mdshdr_tree_trlr;
    int offset = 0;
    guint    pktlen;
    tvbuff_t *next_tvb;
    guint8 sof, eof;
    guint16 vsan;
    guint8 span_id;
    int trailer_start = 0; /*0 means "no trailer found"*/

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

    sof = tvb_get_guint8 (tvb, offset+MDSHDR_SOF_OFFSET) & 0x0F;
    pktlen = tvb_get_ntohs (tvb, offset+MDSHDR_PKTLEN_OFFSET) & 0x1FFF;
    vsan = tvb_get_ntohs (tvb, offset+MDSHDR_VSAN_OFFSET) & 0x0FFF;
    span_id = (tvb_get_ntohs (tvb, offset+MDSHDR_VSAN_OFFSET) & 0xF000) >> 12;
    
    /* The Mdshdr trailer is at the end of the frame */
    if (tvb_length (tvb) >= MDSHDR_HEADER_SIZE + pktlen
     /* Avoid header/trailer overlap if something wrong */
     && pktlen >= MDSHDR_TRAILER_SIZE ) {
        trailer_start = MDSHDR_HEADER_SIZE + pktlen - MDSHDR_TRAILER_SIZE; 
    
        eof = tvb_get_guint8 (tvb, trailer_start);
        tvb_set_reported_length (tvb, MDSHDR_HEADER_SIZE+pktlen);
    }
    else {
        eof = MDSHDR_EOF_UNKNOWN;
    }

    pinfo->src_idx = (tvb_get_ntohs (tvb, MDSHDR_SIDX_OFFSET) & 0x3FF);
    pinfo->dst_idx = (tvb_get_ntohs (tvb, MDSHDR_DIDX_OFFSET) & 0xFFC) >> 2;
    pinfo->vsan = vsan;
    pinfo->sof_eof = 0;

    if ((sof == MDSHDR_SOFi3) || (sof == MDSHDR_SOFi2) || (sof == MDSHDR_SOFi1)
        || (sof == MDSHDR_SOFi4)) {
        pinfo->sof_eof = PINFO_SOF_FIRST_FRAME;
    }
    else if (sof == MDSHDR_SOFf) {
        pinfo->sof_eof = PINFO_SOF_SOFF;      
    }

    if (eof != MDSHDR_EOFn) {
        pinfo->sof_eof |= PINFO_EOF_LAST_FRAME;
    }
    else if (eof != MDSHDR_EOFt) {
        pinfo->sof_eof |= PINFO_EOF_INVALID;
    }
    
    /* In the interest of speed, if "tree" is NULL, don't do any work not
       necessary to generate protocol tree items. */
    if (tree) {

        /* create display subtree for the protocol */
        ti_main = proto_tree_add_protocol_format (tree, proto_mdshdr, tvb, 0,
                                                  MDSHDR_HEADER_SIZE+pktlen,
                                                  "MDS Header(%s/%s)", 
						  val_to_str(sof, sof_vals, "Unknown(%u)"),
                                                  val_to_str(eof, eof_vals, "Unknown(%u)"));

        mdshdr_tree_main = proto_item_add_subtree (ti_main, ett_mdshdr);

        /* Add Header part as subtree first */
        ti_hdr = proto_tree_add_text (mdshdr_tree_main, tvb, MDSHDR_VER_OFFSET,
                                      MDSHDR_HEADER_SIZE, "MDS Header");

        mdshdr_tree_hdr = proto_item_add_subtree (ti_hdr, ett_mdshdr_hdr);
        hidden_item = proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_sof, tvb, MDSHDR_SOF_OFFSET,
                                    MDSHDR_SIZE_BYTE, 0);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
        proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_pkt_len, tvb, MDSHDR_PKTLEN_OFFSET, 
                             MDSHDR_SIZE_INT16, 0);
        proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_dstidx, tvb, MDSHDR_DIDX_OFFSET,
                             MDSHDR_SIZE_INT16, 0);
        proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_srcidx, tvb, MDSHDR_SIDX_OFFSET,
                             MDSHDR_SIZE_INT16, 0);
        proto_tree_add_item (mdshdr_tree_hdr, hf_mdshdr_vsan, tvb, MDSHDR_VSAN_OFFSET,
                             MDSHDR_SIZE_INT16, 0);
        hidden_item = proto_tree_add_uint(mdshdr_tree_hdr, hf_mdshdr_span,
                                   tvb, MDSHDR_VSAN_OFFSET,
                                   MDSHDR_SIZE_BYTE, span_id);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
        
        /* Add Mdshdr Trailer part */
        if (tvb_length (tvb) >= MDSHDR_HEADER_SIZE + pktlen
         && 0 != trailer_start) {
            ti_trlr = proto_tree_add_text (mdshdr_tree_main, tvb, trailer_start,
                                           MDSHDR_TRAILER_SIZE,
                                           "MDS Trailer");
            mdshdr_tree_trlr = proto_item_add_subtree (ti_trlr, ett_mdshdr_trlr);
        
            proto_tree_add_item (mdshdr_tree_trlr, hf_mdshdr_eof, tvb,
                                 trailer_start, MDSHDR_SIZE_BYTE, 0);
            proto_tree_add_item (mdshdr_tree_trlr, hf_mdshdr_fccrc, tvb,
                                 trailer_start+2, MDSHDR_SIZE_INT32, 0);
        }
        else {
            proto_tree_add_text (mdshdr_tree_main, tvb, 0, 0, "MDS Trailer: Not Found");        
        }
    }
    
    /* If this protocol has a sub-dissector call it here, see section 1.8 */
    if (tvb_length (tvb) >= MDSHDR_HEADER_SIZE + pktlen
     && 0 != pktlen /*if something wrong*/) {
        next_tvb = tvb_new_subset (tvb, MDSHDR_HEADER_SIZE, pktlen, pktlen);
        /* XXX what to do with the rest of this frame? --ArtemTamazov */
    }
    else {
        next_tvb = tvb_new_subset_remaining (tvb, MDSHDR_HEADER_SIZE);
    }

    /* Call the Fibre Channel dissector */
    if (fc_dissector_handle) {
        call_dissector (fc_dissector_handle, next_tvb, pinfo, tree);
    }
    else {
        call_dissector (data_handle, next_tvb, pinfo, tree);
    }
}
Ejemplo n.º 16
0
static void
dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_tree     *clnp_tree = NULL;
  proto_item     *ti;
  guint8          cnf_proto_id;
  guint8          cnf_hdr_len;
  guint8          cnf_vers;
  guint8          cnf_ttl;
  guint8          cnf_type;
  char            flag_string[6+1];
  const char     *pdu_type_string;
  proto_tree     *type_tree;
  guint16         segment_length;
  guint16         du_id = 0;
  guint16         segment_offset = 0;
  guint16         cnf_cksum;
  cksum_status_t  cksum_status;
  int             offset;
  guchar          src_len, dst_len, nsel, opt_len = 0;
  const guint8   *dst_addr, *src_addr;
  guint           next_length;
  proto_tree     *discpdu_tree;
  gboolean        save_in_error_pkt;
  fragment_data  *fd_head;
  tvbuff_t       *next_tvb;
  gboolean        update_col_info = TRUE;
  gboolean        save_fragmented;

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

  cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID);
  if (cnf_proto_id == NLPID_NULL) {
    col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset");
    if (tree) {
      ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, ENC_NA);
      clnp_tree = proto_item_add_subtree(ti, ett_clnp);
      proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
                                 cnf_proto_id,
                                 "Inactive subset");
    }
    next_tvb = tvb_new_subset_remaining(tvb, 1);
    if (call_dissector(ositp_inactive_handle, next_tvb, pinfo, tree) == 0)
      call_dissector(data_handle,tvb, pinfo, tree);
    return;
  }

  /* return if version not known */
  cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS);
  if (cnf_vers != ISO8473_V1) {
    call_dissector(data_handle,tvb, pinfo, tree);
    return;
  }

  /* fixed part decoding */
  cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
  opt_len = cnf_hdr_len;

  if (tree) {
    ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA);
    clnp_tree = proto_item_add_subtree(ti, ett_clnp);
    proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
                        cnf_proto_id);
    proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
                        cnf_hdr_len);
    proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
                        cnf_vers);
    cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
    proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
                               cnf_ttl,
                               "Holding Time : %u (%u.%u secs)",
                               cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
  }

  cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
  pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
                               "Unknown (0x%02x)");
  flag_string[0] = '\0';
  if (cnf_type & CNF_SEG_OK)
    g_strlcat(flag_string, "S ", 7);
  if (cnf_type & CNF_MORE_SEGS)
    g_strlcat(flag_string, "M ", 7);
  if (cnf_type & CNF_ERR_OK)
    g_strlcat(flag_string, "E ", 7);
  if (tree) {
    ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
                                    cnf_type,
                                    "PDU Type     : 0x%02x (%s%s)",
                                    cnf_type,
                                    flag_string,
                                    pdu_type_string);
    type_tree = proto_item_add_subtree(ti, ett_clnp_type);
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_boolean_bitfield(cnf_type, CNF_SEG_OK, 8,
                                                "Segmentation permitted",
                                                "Segmentation not permitted"));
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_boolean_bitfield(cnf_type, CNF_MORE_SEGS, 8,
                                                "More segments",
                                                "Last segment"));
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_boolean_bitfield(cnf_type, CNF_ERR_OK, 8,
                                                "Report error if PDU discarded",
                                                "Don't report error if PDU discarded"));
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_enumerated_bitfield(cnf_type, CNF_TYPE, 8,
                                                   npdu_type_vals, "%s"));
  }

  /* If we don't have the full header - i.e., not enough to see the
     segmentation part and determine whether this datagram is segmented
     or not - set the Info column now; we'll get an exception before
     we set it otherwise. */

  if (tvb_length(tvb) < cnf_hdr_len) {
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
  }

  segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
  cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
  cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum);
  if (tree) {
    proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
                        segment_length);
    switch (cksum_status) {

    default:
      /*
       * No checksum present, or not enough of the header present to
       * checksum it.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x",
                                 cnf_cksum);
      break;

    case CKSUM_OK:
      /*
       * Checksum is correct.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x (correct)",
                                 cnf_cksum);
      break;

    case CKSUM_NOT_OK:
      /*
       * Checksum is not correct.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x (incorrect)",
                                 cnf_cksum);
      break;
    }
    opt_len -= 9; /* Fixed part of Hesder */
  } /* tree */

  /* address part */

  offset = P_CLNP_ADDRESS_PART;
  dst_len  = tvb_get_guint8(tvb, offset);
  dst_addr = tvb_get_ptr(tvb, offset + 1, dst_len);
  nsel     = tvb_get_guint8(tvb, offset + dst_len);
  src_len  = tvb_get_guint8(tvb, offset + dst_len + 1);
  src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len);

  if (tree) {
    proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
                        dst_len);
    proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset + 1 , dst_len,
                                dst_addr,
                                " DA : %s",
                                print_nsap_net(dst_addr, dst_len));
    proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
                        offset + 1 + dst_len, 1, src_len);
    proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb,
                                offset + dst_len + 2, src_len,
                                src_addr,
                                " SA : %s",
                                print_nsap_net(src_addr, src_len));

    opt_len -= dst_len + src_len +2;
  }

  SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr);
  SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr);
  SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr);
  SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr);

  /* Segmentation Part */

  offset += dst_len + src_len + 2;

  if (cnf_type & CNF_SEG_OK) {
#if 0
    struct clnp_segment seg;                                /* XXX - not used */
    tvb_memcpy(tvb, (guint8 *)&seg, offset, sizeof(seg));   /* XXX - not used */
#endif

    segment_offset = tvb_get_ntohs(tvb, offset + 2);
    du_id = tvb_get_ntohs(tvb, offset);
    if (tree) {
      proto_tree_add_text(clnp_tree, tvb, offset, 2,
                          "Data unit identifier: %06u",
                          du_id);
      proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
                          "Segment offset      : %6u",
                          segment_offset);
      proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
                          "Total length        : %6u",
                          tvb_get_ntohs(tvb, offset + 4));
    }

    offset  += 6;
    opt_len -= 6;
  }

  if (tree) {
    /* To do : decode options  */
#if 0
    proto_tree_add_text(clnp_tree, tvb, offset,
                        cnf_hdr_len - offset,
                        "Options/Data: <not shown>");
#endif
/* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/

    dissect_osi_options( opt_len,
                         tvb, offset, clnp_tree );
  }

  offset = cnf_hdr_len;

  /* If clnp_reassemble is on, this is a segment, we have all the
   * data in the segment, and the checksum is valid, then just add the
   * segment to the hashtable.
   */
  save_fragmented = pinfo->fragmented;
  if (clnp_reassemble && (cnf_type & CNF_SEG_OK) &&
      ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) &&
      tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) &&
      segment_length > cnf_hdr_len &&
      cksum_status != CKSUM_NOT_OK) {
    fd_head = fragment_add_check(tvb, offset, pinfo, du_id, clnp_segment_table,
                                 clnp_reassembled_table, segment_offset,
                                 segment_length - cnf_hdr_len,
                                 cnf_type & CNF_MORE_SEGS);

    next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP",
                                        fd_head, &clnp_frag_items, &update_col_info, clnp_tree);
  } else {
    /* If this is the first segment, dissect its contents, otherwise
       just show it as a segment.

       XXX - if we eventually don't save the reassembled contents of all
       segmented datagrams, we may want to always reassemble. */
    if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
      /* Not the first segment - don't dissect it. */
      next_tvb = NULL;
    } else {
      /* First segment, or not segmented.  Dissect what we have here. */

      /* Get a tvbuff for the payload. */
      next_tvb = tvb_new_subset_remaining(tvb, offset);

      /*
       * If this is the first segment, but not the only segment,
       * tell the next protocol that.
       */
      if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS))
        pinfo->fragmented = TRUE;
      else
        pinfo->fragmented = FALSE;
    }
  }

  if (next_tvb == NULL) {
    /* Just show this as a segment. */
    col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
                 pdu_type_string, flag_string, segment_offset);

    /* As we haven't reassembled anything, we haven't changed "pi", so
       we don't have to restore it. */
    call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo,
                   tree);
    pinfo->fragmented = save_fragmented;
    return;
  }

  if (tvb_offset_exists(tvb, offset)) {
    switch (cnf_type & CNF_TYPE) {

    case DT_NPDU:
    case MD_NPDU:
      /* Continue with COTP if any data.
         XXX - if this isn't the first Derived PDU of a segmented Initial
         PDU, skip that? */

      if (nsel == (guchar)tp_nsap_selector || always_decode_transport) {
        if (call_dissector(ositp_handle, next_tvb, pinfo, tree) != 0) {
          pinfo->fragmented = save_fragmented;
          return;       /* yes, it appears to be COTP or CLTP */
        }
      }
      if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb,
                                  pinfo, tree)) {
          pinfo->fragmented = save_fragmented;
          return;       /* yes, it appears to be one of the protocols in the heuristic list */
      }

      break;

    case ER_NPDU:
      /* The payload is the header and "none, some, or all of the data
         part of the discarded PDU", i.e. it's like an ICMP error;
         dissect it as a CLNP PDU. */

      col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
      next_length = tvb_length_remaining(tvb, offset);
      if (next_length != 0) {
          /* We have payload; dissect it. */
          ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length,
            "Discarded PDU");
          discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu);

          /* Save the current value of the "we're inside an error packet"
             flag, and set that flag; subdissectors may treat packets
             that are the payload of error packets differently from
             "real" packets. */
          save_in_error_pkt = pinfo->flags.in_error_pkt;
          pinfo->flags.in_error_pkt = TRUE;

          call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);

          /* Restore the "we're inside an error packet" flag. */
          pinfo->flags.in_error_pkt = save_in_error_pkt;
      }
      pinfo->fragmented = save_fragmented;
      return;   /* we're done with this PDU */

    case ERQ_NPDU:
    case ERP_NPDU:
      /* XXX - dissect this */
      break;
    }
  }
  col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
  call_dissector(data_handle,next_tvb, pinfo, tree);
  pinfo->fragmented = save_fragmented;
} /* dissect_clnp */
Ejemplo n.º 17
0
static void
dissect_llc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*llc_tree;
	proto_tree	*field_tree;
	proto_item	*ti, *sap_item;
	int		is_snap;
	guint16		control;
	int		llc_header_len;
	guint8		dsap, ssap, format;
	tvbuff_t	*next_tvb;

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

	dsap = tvb_get_guint8(tvb, 0);

	ti = proto_tree_add_item(tree, proto_llc, tvb, 0, -1, ENC_NA);
	llc_tree = proto_item_add_subtree(ti, ett_llc);
	sap_item = proto_tree_add_item(llc_tree, hf_llc_dsap, tvb, 0, 1, ENC_NA);
	field_tree = proto_item_add_subtree(sap_item, ett_llc_dsap);
	proto_tree_add_item(field_tree, hf_llc_dsap_sap, tvb, 0, 1, ENC_NA);
	proto_tree_add_item(field_tree, hf_llc_dsap_ig, tvb, 0, 1, ENC_NA);

	ssap = tvb_get_guint8(tvb, 1);
	sap_item = proto_tree_add_item(llc_tree, hf_llc_ssap, tvb, 1, 1, ENC_NA);
	field_tree = proto_item_add_subtree(sap_item, ett_llc_ssap);
	proto_tree_add_item(field_tree, hf_llc_ssap_sap, tvb, 1, 1, ENC_NA);
	proto_tree_add_item(field_tree, hf_llc_ssap_cr, tvb, 1, 1, ENC_NA);

	is_snap = (dsap == SAP_SNAP) && (ssap == SAP_SNAP);
	llc_header_len = 2;	/* DSAP + SSAP */

	/*
	 * XXX - the page referred to in the comment above about the
	 * Command/Response bit also implies that LLC Type 2 always
	 * uses extended operation, so we don't need to determine
	 * whether it's basic or extended operation; is that the case?
	 */
	control = dissect_xdlc_control(tvb, 2, pinfo, llc_tree,
				hf_llc_ctrl, ett_llc_ctrl,
				&llc_cf_items, &llc_cf_items_ext,
				NULL, NULL, ssap & SSAP_CR_BIT, TRUE, FALSE);
	llc_header_len += XDLC_CONTROL_LEN(control, TRUE);
	if (is_snap)
		llc_header_len += 5;	/* 3 bytes of OUI, 2 bytes of protocol ID */

	if (tree)
		proto_item_set_len(ti, llc_header_len);

	if (is_snap) {
		dissect_snap(tvb, 2+XDLC_CONTROL_LEN(control, TRUE), pinfo, tree, llc_tree, control,
		    hf_llc_oui, hf_llc_type, hf_llc_pid, 2);
	}
	else {
		col_append_fstr(pinfo->cinfo, COL_INFO,
			    "; DSAP %s %s, SSAP %s %s",
			    val_to_str(dsap & SAP_MASK, sap_vals, "0x%02x"),
			    dsap & DSAP_GI_BIT ?
			      "Group" : "Individual",
			    val_to_str(ssap & SAP_MASK, sap_vals, "0x%02x"),
			    ssap & SSAP_CR_BIT ?
			      "Response" : "Command"
			);

		if (tvb_reported_length_remaining(tvb, llc_header_len) > 0) {
			next_tvb = tvb_new_subset_remaining(tvb, llc_header_len);
			if (XDLC_IS_INFORMATION(control)) {
				/*
				 * Non-SNAP I or UI frame.
				 * Try the regular LLC subdissector table
				 * with the DSAP.
				 */
				if (!dissector_try_uint(dsap_subdissector_table,
				    dsap, next_tvb, pinfo, tree)) {
					call_dissector(data_handle, next_tvb,
					    pinfo, tree);
				}
			} else if ((control & (XDLC_U_MODIFIER_MASK|XDLC_U))
			    == (XDLC_XID|XDLC_U)) {
				/*
				 * Non-SNAP XID frame.
				 * Test for LLC basic format first
				 */
				format = tvb_get_guint8(next_tvb, 0);
				if (format == 0x81) {
				    dissect_basicxid(next_tvb, pinfo, tree);
				} else {
				/*
				 * Try the XID LLC subdissector table
				 * with the DSAP.
				 */
				    if (!dissector_try_uint(
					xid_subdissector_table, dsap, next_tvb,
					pinfo, tree)) {
					    call_dissector(data_handle,
						next_tvb, pinfo, tree);
				    }
				}
			} else {
				call_dissector(data_handle, next_tvb, pinfo,
				    tree);
			}
		}
	}
}
/* Parse Short Message, only if UDH present
 * (otherwise this function is not called).
 * Call WSP dissector if port matches WSP traffic.
 */
static void
parse_gsm_sms_ud_message(proto_tree *sm_tree, tvbuff_t *tvb, packet_info *pinfo,
                         proto_tree *top_tree)
{
    tvbuff_t *sm_tvb = NULL;
    proto_item *subtree, *tree;
    guint8 udh_len, udh, len;
    guint sm_len = tvb_reported_length (tvb);
    guint sm_data_len;
    guint32 i = 0;
    /* Multiple Messages UDH */
    gboolean is_fragmented = FALSE;
    fragment_data *fd_sm = NULL;
    guint16 sm_id = 0, frags = 0, frag = 0;
    gboolean save_fragmented = FALSE, try_gsm_sms_ud_reassemble = FALSE;
    /* SMS Message reassembly */
    gboolean reassembled = FALSE;
    guint32 reassembled_in = 0;
    /* Port Number UDH */
    guint16 p_src = 0, p_dst = 0;
    gboolean ports_available = FALSE;

    udh_len = tvb_get_guint8(tvb, i++);
    tree = proto_tree_add_uint(sm_tree, hf_gsm_sms_udh_length, tvb, 0, 1, udh_len);
    tree = proto_item_add_subtree(tree, ett_udh);
    while (i < udh_len) {
        udh = tvb_get_guint8(tvb, i++);
        len = tvb_get_guint8(tvb, i++);
        subtree = proto_tree_add_uint(tree, hf_gsm_sms_udh_iei,
                                      tvb, i-2, 2+len, udh);
        switch (udh) {
        case 0x00: /* Multiple messages - 8-bit message ID */
            if (len == 3) {
                sm_id = tvb_get_guint8(tvb, i++);
                frags = tvb_get_guint8(tvb, i++);
                frag  = tvb_get_guint8(tvb, i++);
                if (frags > 1)
                    is_fragmented = TRUE;
                proto_item_append_text(subtree,
                                       ": message %u, part %u of %u", sm_id, frag, frags);
                subtree = proto_item_add_subtree(subtree,
                                                 ett_udh_ie);
                proto_tree_add_uint (subtree,
                                     hf_gsm_sms_udh_multiple_messages_msg_id,
                                     tvb, i-3, 1, sm_id);
                proto_tree_add_uint (subtree,
                                     hf_gsm_sms_udh_multiple_messages_msg_parts,
                                     tvb, i-2, 1, frags);
                proto_tree_add_uint (subtree,
                                     hf_gsm_sms_udh_multiple_messages_msg_part,
                                     tvb, i-1, 1, frag);
            } else {
                proto_item_append_text(subtree, " - Invalid format!");
                i += len;
            }
            break;

        case 0x08: /* Multiple messages - 16-bit message ID */
            if (len == 4) {
                sm_id = tvb_get_ntohs(tvb, i);
                i += 2;
                frags = tvb_get_guint8(tvb, i++);
                frag  = tvb_get_guint8(tvb, i++);
                if (frags > 1)
                    is_fragmented = TRUE;
                proto_item_append_text(subtree,
                                       ": message %u, part %u of %u", sm_id, frag, frags);
                subtree = proto_item_add_subtree(subtree,
                                                 ett_udh_ie);
                proto_tree_add_uint (subtree,
                                     hf_gsm_sms_udh_multiple_messages_msg_id,
                                     tvb, i-4, 2, sm_id);
                proto_tree_add_uint (subtree,
                                     hf_gsm_sms_udh_multiple_messages_msg_parts,
                                     tvb, i-2, 1, frags);
                proto_tree_add_uint (subtree,
                                     hf_gsm_sms_udh_multiple_messages_msg_part,
                                     tvb, i-1, 1, frag);
            } else {
                proto_item_append_text(subtree, " - Invalid format!");
                i += len;
            }
            break;

        case 0x04: /* Port Number UDH - 8-bit address */
            if (len == 2) { /* Port fields */
                p_dst = tvb_get_guint8(tvb, i++);
                p_src = tvb_get_guint8(tvb, i++);
                proto_item_append_text(subtree,
                                       ": source port %u, destination port %u",
                                       p_src, p_dst);
                subtree = proto_item_add_subtree(subtree, ett_udh_ie);
                proto_tree_add_uint (subtree, hf_gsm_sms_udh_ports_dst,
                                     tvb, i-2, 1, p_dst);
                proto_tree_add_uint (subtree, hf_gsm_sms_udh_ports_src,
                                     tvb, i-1, 1, p_src);
                ports_available = TRUE;
            } else {
                proto_item_append_text(subtree, " - Invalid format!");
                i += len;
            }
            break;

        case 0x05: /* Port Number UDH - 16-bit address */
            if (len == 4) { /* Port fields */
                p_dst = tvb_get_ntohs(tvb, i);
                i += 2;
                p_src = tvb_get_ntohs(tvb, i);
                i += 2;
                proto_item_append_text(subtree,
                                       ": source port %u, destination port %u",
                                       p_src, p_dst);
                subtree = proto_item_add_subtree(subtree, ett_udh_ie);
                proto_tree_add_uint (subtree, hf_gsm_sms_udh_ports_dst,
                                     tvb, i-4, 2, p_dst);
                proto_tree_add_uint (subtree, hf_gsm_sms_udh_ports_src,
                                     tvb, i-2, 2, p_src);
                ports_available = TRUE;
            } else {
                proto_item_append_text(subtree, " - Invalid format!");
                i += len;
            }
            break;

        default:
            i += len;
            break;
        }
    }
    if (tvb_reported_length_remaining(tvb, i) <= 0)
        return; /* No more data */

    /*
     * XXX - where does the "1" come from?  If it weren't there,
     * "sm_data_len" would, I think, be the same as
     * "tvb_reported_length_remaining(tvb, i)".
     *
     * I think that the above check ensures that "sm_len" won't
     * be less than or equal to "udh_len", so it ensures that
     * "sm_len" won't be less than "1 + udh_len", so we don't
     * have to worry about "sm_data_len" being negative.
     */
    sm_data_len = sm_len - (1 + udh_len);
    if (sm_data_len == 0)
        return;	/* no more data */

    /*
     * Try reassembling the packets.
     * XXX - fragment numbers are 1-origin, but the fragment number
     * field could be 0.
     * Should we flag a fragmented message with a fragment number field
     * of 0?
     * What if the fragment count is 0?  Should we flag that as well?
     */
    if ( is_fragmented && frag != 0 && frags != 0 &&
            tvb_bytes_exist (tvb, i, sm_data_len) ) {
        try_gsm_sms_ud_reassemble = TRUE;
        save_fragmented = pinfo->fragmented;
        pinfo->fragmented = TRUE;
        fd_sm = fragment_add_seq_check (tvb, i, pinfo,
                                        sm_id, /* guint32 ID for fragments belonging together */
                                        sm_fragment_table, /* list of message fragments */
                                        sm_reassembled_table, /* list of reassembled messages */
                                        frag-1, /* guint32 fragment sequence number */
                                        sm_data_len, /* guint32 fragment length */
                                        (frag != frags)); /* More fragments? */
        if (fd_sm) {
            reassembled = TRUE;
            reassembled_in = fd_sm->reassembled_in;
        }
        sm_tvb = process_reassembled_data(tvb, i, pinfo,
                                          "Reassembled Short Message", fd_sm, &sm_frag_items,
                                          NULL, sm_tree);
        if (reassembled) { /* Reassembled */
            col_append_str (pinfo->cinfo, COL_INFO,
                            " (Short Message Reassembled)");
        } else {
            /* Not last packet of reassembled Short Message */
            col_append_fstr (pinfo->cinfo, COL_INFO,
                             " (Short Message fragment %u of %u)", frag, frags);
        }
    } /* Else: not fragmented */

    if (! sm_tvb) /* One single Short Message, or not reassembled */
        sm_tvb = tvb_new_subset_remaining (tvb, i);
    /* Try calling a subdissector */
    if (sm_tvb) {
        if ((reassembled && pinfo->fd->num == reassembled_in)
                || frag==0 || (frag==1 && try_dissect_1st_frag)) {
            /* Try calling a subdissector only if:
             *  - the Short Message is reassembled in this very packet,
             *  - the Short Message consists of only one "fragment",
             *  - the preference "Always Try Dissection for 1st SM fragment"
             *    is switched on, and this is the SM's 1st fragment. */
            if ( ports_available ) {
                gboolean disallow_write = FALSE; /* TRUE if we changed writability
								    of the columns of the summary */
                if ( prevent_subdissectors_changing_columns && col_get_writable(pinfo->cinfo) ) {
                    disallow_write = TRUE;
                    col_set_writable(pinfo->cinfo, FALSE);
                }

                if ( port_number_udh_means_wsp ) {
                    call_dissector (wsp_handle, sm_tvb, pinfo, top_tree);
                } else {
                    if (! dissector_try_uint(gsm_sms_dissector_table, p_src,
                                             sm_tvb, pinfo, top_tree)) {
                        if (! dissector_try_uint(gsm_sms_dissector_table, p_dst,
                                                 sm_tvb, pinfo, top_tree)) {
                            if (sm_tree) { /* Only display if needed */
                                proto_tree_add_text (sm_tree, sm_tvb, 0, -1,
                                                     "Short Message body");
                            }
                        }
                    }
                }

                if ( disallow_write )
                    col_set_writable(pinfo->cinfo, TRUE);
            } else { /* No ports IE */
                proto_tree_add_text (sm_tree, sm_tvb, 0, -1,
                                     "Short Message body");
            }
        } else {
            /* The packet is not reassembled,
             * or it is reassembled in another packet */
            proto_tree_add_text (sm_tree, sm_tvb, 0, -1,
                                 "Unreassembled Short Message fragment %u of %u",
                                 frag, frags);
        }
    }

    if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */
        pinfo->fragmented = save_fragmented;
    return;
}
Ejemplo n.º 19
0
static void
dissect_sita(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item  *ti;
    guchar      flags, signals, errors1, errors2, proto;
    const gchar *errors1_string, *errors2_string, *flags_string;
    proto_tree  *sita_tree          = NULL;
    proto_tree  *sita_flags_tree    = NULL;
    proto_tree  *sita_errors1_tree  = NULL;
    proto_tree  *sita_errors2_tree  = NULL;
    static const gchar *rx_errors1_str[]   = {"Framing",       "Parity",   "Collision",    "Long-frame",   "Short-frame",  "",         "",     ""              };
    static const gchar *rx_errors2_str[]   = {"Non-Aligned",   "Abort",    "CD-lost",      "DPLL",         "Overrun",      "Length",   "CRC",  "Break"         };
#if 0
    static const gchar   *tx_errors1_str[]   = {"",              "",         "",             "",             "",             "",         "",     ""              };
#endif
    static const gchar *tx_errors2_str[]   = {"Underrun",      "CTS-lost", "UART",         "ReTx-limit",   "",             "",         "",     ""              };
    static const gchar *flags_str[]        = {"",              "",         "",             "",             "",             "",         "",     "No-buffers"    };


    static const int * signal_flags[] = {
        &hf_dcd,
        &hf_rts,
        &hf_cts,
        &hf_dtr,
        &hf_dsr,
        NULL
    };

    col_clear(pinfo->cinfo, COL_PROTOCOL);      /* erase the protocol */
    col_clear(pinfo->cinfo, COL_INFO);          /* and info columns so that the next decoder can fill them in */

    flags   = pinfo->pseudo_header->sita.sita_flags;
    signals = pinfo->pseudo_header->sita.sita_signals;
    errors1 = pinfo->pseudo_header->sita.sita_errors1;
    errors2 = pinfo->pseudo_header->sita.sita_errors2;
    proto   = pinfo->pseudo_header->sita.sita_proto;

    if ((flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_TXED) {
        col_set_str(pinfo->cinfo, COL_DEF_SRC, IOP);  /* set the source (direction) column accordingly */
    } else {
        col_set_str(pinfo->cinfo, COL_DEF_SRC, REMOTE);
    }

    col_set_str(pinfo->cinfo, COL_INFO, "");

    if (tree) {
        ti = proto_tree_add_protocol_format(tree, proto_sita, tvb, 0, 0, "Link Layer");
        sita_tree = proto_item_add_subtree(ti, ett_sita);

        proto_tree_add_uint(sita_tree, hf_proto, tvb, 0, 0, proto);

        flags_string = format_flags_string(flags, flags_str);
        sita_flags_tree = proto_tree_add_subtree_format(sita_tree, tvb, 0, 0,
                ett_sita_flags, NULL, "Flags: 0x%02x (From %s)%s%s",
                flags,
                ((flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_TXED) ? IOP : REMOTE,
                strlen(flags_string) ? ", " : "",
                flags_string);
        proto_tree_add_boolean(sita_flags_tree, hf_droppedframe,    tvb, 0, 0, flags);
        proto_tree_add_boolean(sita_flags_tree, hf_dir,             tvb, 0, 0, flags);

        proto_tree_add_bitmask_value_with_flags(sita_tree, tvb, 0, hf_signals, ett_sita_signals,
                                                signal_flags, signals, BMT_NO_FALSE|BMT_NO_TFS);

        if ((flags & SITA_FRAME_DIR) == SITA_FRAME_DIR_RXED) {
            errors1_string = format_flags_string(errors1, rx_errors1_str);
            sita_errors1_tree = proto_tree_add_subtree_format(sita_tree, tvb, 0, 0,
                ett_sita_errors1, NULL, "Receive Status: 0x%02x %s", errors1, errors1_string);
            proto_tree_add_boolean(sita_errors1_tree, hf_shortframe,    tvb, 0, 0, errors1);
            proto_tree_add_boolean(sita_errors1_tree, hf_longframe,     tvb, 0, 0, errors1);
            proto_tree_add_boolean(sita_errors1_tree, hf_collision,     tvb, 0, 0, errors1);
            proto_tree_add_boolean(sita_errors1_tree, hf_parity,        tvb, 0, 0, errors1);
            proto_tree_add_boolean(sita_errors1_tree, hf_framing,       tvb, 0, 0, errors1);

            errors2_string = format_flags_string(errors2, rx_errors2_str);
            sita_errors2_tree = proto_tree_add_subtree_format(sita_tree, tvb, 0, 0,
                ett_sita_errors2, NULL, "Receive Status: 0x%02x %s", errors2, errors2_string);
            proto_tree_add_boolean(sita_errors2_tree, hf_break,         tvb, 0, 0, errors2);
            proto_tree_add_boolean(sita_errors2_tree, hf_crc,           tvb, 0, 0, errors2);
            proto_tree_add_boolean(sita_errors2_tree, hf_length,        tvb, 0, 0, errors2);
            proto_tree_add_boolean(sita_errors2_tree, hf_overrun,       tvb, 0, 0, errors2);
            proto_tree_add_boolean(sita_errors2_tree, hf_rxdpll,        tvb, 0, 0, errors2);
            proto_tree_add_boolean(sita_errors2_tree, hf_lostcd,        tvb, 0, 0, errors2);
            proto_tree_add_boolean(sita_errors2_tree, hf_abort,         tvb, 0, 0, errors2);
            proto_tree_add_boolean(sita_errors2_tree, hf_nonaligned,    tvb, 0, 0, errors2);
        } else {
            errors2_string = format_flags_string(errors2, tx_errors2_str);
            sita_errors1_tree = proto_tree_add_subtree_format(sita_tree, tvb, 0, 0,
                ett_sita_errors1, NULL, "Transmit Status: 0x%02x %s", errors2, errors2_string);
            proto_tree_add_boolean(sita_errors1_tree, hf_rtxlimit,      tvb, 0, 0, errors2);
            proto_tree_add_boolean(sita_errors1_tree, hf_uarterror,     tvb, 0, 0, errors2);
            proto_tree_add_boolean(sita_errors1_tree, hf_lostcts,       tvb, 0, 0, errors2);
            proto_tree_add_boolean(sita_errors1_tree, hf_underrun,      tvb, 0, 0, errors2);
        }
    }

    /* try to find and run an applicable dissector */
    if (!dissector_try_uint(sita_dissector_table, pinfo->pseudo_header->sita.sita_proto, tvb, pinfo, tree)) {
        /* if one can't be found... tell them we don't know how to decode this protocol
           and give them the details then */
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
        col_add_fstr(pinfo->cinfo, COL_INFO, "IOP protocol number: %u", pinfo->pseudo_header->sita.sita_proto);
        call_dissector(data_handle, tvb, pinfo, tree);          /* call the generic (hex display) decoder instead */
    }
}
Ejemplo n.º 20
0
static void
dissect_eapol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  int         offset = 0;
  guint8      eapol_type;
  guint8      keydesc_type;
  guint16     eapol_len;
  guint       len;
  guint16     eapol_key_len, eapol_data_len;
  guint16     keyinfo;
  gboolean    generated_locally;
  proto_tree *ti = NULL;
  proto_tree *eapol_tree = NULL;
  proto_tree *keyinfo_item = NULL;
  proto_tree *keyinfo_tree = NULL;
  proto_tree *key_index_tree, *keydes_tree;
  tvbuff_t   *next_tvb;

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

  if (tree) {
    ti = proto_tree_add_item(tree, proto_eapol, tvb, 0, -1, ENC_NA);
    eapol_tree = proto_item_add_subtree(ti, ett_eapol);

    proto_tree_add_item(eapol_tree, hf_eapol_version, tvb, offset, 1, ENC_BIG_ENDIAN);
  }
  offset++;

  eapol_type = tvb_get_guint8(tvb, offset);
  if (tree)
    proto_tree_add_item(eapol_tree, hf_eapol_type, tvb, offset, 1, ENC_BIG_ENDIAN);
  if (check_col(pinfo->cinfo, COL_INFO))
    col_add_str(pinfo->cinfo, COL_INFO,
                val_to_str(eapol_type, eapol_type_vals, "Unknown Type (0x%02X)"));
  offset++;

  eapol_len = tvb_get_ntohs(tvb, offset);
  len = EAPOL_HDR_LEN + eapol_len;
  set_actual_length(tvb, len);
  if (tree) {
    proto_item_set_len(ti, len);
    proto_tree_add_item(eapol_tree, hf_eapol_len, tvb, offset, 2, ENC_BIG_ENDIAN);
  }
  offset += 2;

  switch (eapol_type) {

  case EAP_PACKET:
    next_tvb = tvb_new_subset_remaining(tvb, offset);
    call_dissector(eap_handle, next_tvb, pinfo, eapol_tree);
    break;

  case EAPOL_KEY:
    if (tree) {
      keydesc_type = tvb_get_guint8(tvb, offset);
      proto_tree_add_item(eapol_tree, hf_eapol_keydes_type, tvb, offset, 1, ENC_BIG_ENDIAN);
      offset += 1;
      if (keydesc_type == EAPOL_WPA_KEY || keydesc_type == EAPOL_RSN_KEY) {
        keyinfo = tvb_get_ntohs(tvb, offset);
        if (check_col(pinfo->cinfo, COL_INFO)) {
          if (keyinfo & KEY_INFO_REQUEST_MASK) {
            col_set_str(pinfo->cinfo, COL_INFO, "Key (Request)");
            if (keyinfo & KEY_INFO_ERROR_MASK)
              col_set_str(pinfo->cinfo, COL_INFO, "Key (Request, Error)");
          } else if (keyinfo & KEY_INFO_KEY_TYPE_MASK) {
            guint16 masked;
            masked = keyinfo &
              (KEY_INFO_INSTALL_MASK | KEY_INFO_KEY_ACK_MASK |
               KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK);
            switch (masked) {
            case KEY_INFO_KEY_ACK_MASK:
              col_set_str(pinfo->cinfo, COL_INFO, "Key (Message 1 of 4)");
              break;
            case KEY_INFO_KEY_MIC_MASK:
              col_set_str(pinfo->cinfo, COL_INFO, "Key (Message 2 of 4)");
              break;
            case (KEY_INFO_INSTALL_MASK | KEY_INFO_KEY_ACK_MASK |
                  KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK):
              col_set_str(pinfo->cinfo, COL_INFO, "Key (Message 3 of 4)");
              break;
            case (KEY_INFO_KEY_MIC_MASK | KEY_INFO_SECURE_MASK):
              col_set_str(pinfo->cinfo, COL_INFO, "Key (Message 4 of 4)");
              break;
            }
          } else {
            if (keyinfo & KEY_INFO_KEY_ACK_MASK)
              col_set_str(pinfo->cinfo, COL_INFO, "Key (Group Message 1 of 2)");
            else
              col_set_str(pinfo->cinfo, COL_INFO, "Key (Group Message 2 of 2)");
          }
        }
        keyinfo_item =
          proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_keyinfo, tvb,
                              offset, 2, ENC_BIG_ENDIAN);

        keyinfo_tree = proto_item_add_subtree(keyinfo_item, ett_keyinfo);
        proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_keydes_version, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_type, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_index, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_install, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_ack, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_key_mic, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_secure, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_error, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_request, tvb, offset, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(keyinfo_tree, hf_eapol_wpa_keydes_keyinfo_encrypted_key_data, tvb, offset, 2, ENC_BIG_ENDIAN);

        offset += 2;
        proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_len, tvb, offset,
                            2, ENC_BIG_ENDIAN);
        offset += 2;
        proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb,
                            offset, 8, ENC_BIG_ENDIAN);
        offset += 8;
        proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_nonce, tvb, offset,
                            32, ENC_BIG_ENDIAN);
        offset += 32;
        proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb,
                            offset, 16, ENC_BIG_ENDIAN);
        offset += 16;
        proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_rsc, tvb, offset,
                            8, ENC_BIG_ENDIAN);
        offset += 8;
        proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_id, tvb, offset, 8,
                            ENC_BIG_ENDIAN);
        offset += 8;
        proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_mic, tvb, offset,
                            16, ENC_BIG_ENDIAN);
        offset += 16;
        eapol_data_len = tvb_get_ntohs(tvb, offset);
        proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_data_len, tvb,
                            offset, 2, ENC_BIG_ENDIAN);
        offset += 2;
        if (eapol_data_len != 0) {
          ti = proto_tree_add_item(eapol_tree, hf_eapol_wpa_keydes_data,
                tvb, offset, eapol_data_len, ENC_BIG_ENDIAN);
          if ((keyinfo & KEY_INFO_ENCRYPTED_KEY_DATA_MASK) ||
              !(keyinfo & KEY_INFO_KEY_TYPE_MASK)) {
            /* RSN: EAPOL-Key Key Data is encrypted.
             * WPA: Group Keys use encrypted Key Data.
             * Cannot parse this without knowing the key.
             * IEEE 802.11i-2004 8.5.2.
             */
          } else {
            keydes_tree = proto_item_add_subtree(ti, ett_eapol_keydes_data);
            ieee_80211_add_tagged_parameters(tvb, offset, pinfo, keydes_tree,
                                             eapol_data_len, -1);
          }
        }
      } else {
        eapol_key_len = tvb_get_ntohs(tvb, offset);
        proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_len, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;
        proto_tree_add_item(eapol_tree, hf_eapol_keydes_replay_counter, tvb,
                            offset, 8, ENC_BIG_ENDIAN);
        offset += 8;
        proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_iv, tvb,
                            offset, 16, ENC_NA);
        offset += 16;
        ti = proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_index, tvb, offset, 1, ENC_BIG_ENDIAN);
        key_index_tree = proto_item_add_subtree(ti, ett_eapol_key_index);
        proto_tree_add_item(key_index_tree, hf_eapol_keydes_key_index_type,
                            tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(key_index_tree, hf_eapol_keydes_key_index_number,
                            tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;
        proto_tree_add_item(eapol_tree, hf_eapol_keydes_key_signature, tvb,
                            offset, 16, ENC_NA);
        offset += 16;
        if (eapol_key_len != 0) {
          /* IEEE 802.1X-2004 7.6.3.6: If no bytes remain, then */
          generated_locally = eapol_len <= 44; /* Size of rc4 key with no key content */
          if (!generated_locally) {
              proto_tree_add_item(eapol_tree, hf_eapol_keydes_key, tvb, offset,
                                  eapol_key_len, ENC_BIG_ENDIAN);
          }

          proto_tree_add_boolean(eapol_tree, hf_eapol_keydes_key_generated_locally, tvb, offset,
                                 0, generated_locally);
        }
      }
    }
    break;

  case EAPOL_ENCAP_ASF_ALERT:   /* XXX - is this an SNMP trap? */
  default:
    next_tvb = tvb_new_subset_remaining(tvb, offset);
    call_dissector(data_handle, next_tvb, pinfo, eapol_tree);
    break;
  }
}
Ejemplo n.º 21
0
static void dissect_turbocell(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

    proto_item *ti, *name_item;
    proto_tree *turbocell_tree, *network_tree;
    tvbuff_t   *next_tvb;
    int i=0;
    guint8 packet_type;
    guint8 * str_name;
    guint str_len;

    packet_type = tvb_get_guint8(tvb, 0);

    if (!(packet_type & 0x0F)){
        col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Beacon)");
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell");
    }  else if ( packet_type == TURBOCELL_TYPE_MANAGEMENT ) {
        col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Management)");
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell");
    } else if ( packet_type == TURBOCELL_TYPE_DATA ) {
        col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Data)");
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell");
    } else {
        col_set_str(pinfo->cinfo, COL_INFO, "Turbocell Packet (Unknown)");
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "Turbocell");
    }

    if (tree) {
        gint remaining_length;
        ti = proto_tree_add_item(tree, proto_turbocell, tvb, 0, 20, FALSE);

        turbocell_tree = proto_item_add_subtree(ti, ett_turbocell);

        proto_tree_add_item(turbocell_tree, hf_turbocell_type, tvb, 0, 1, FALSE);
        proto_tree_add_item(turbocell_tree, hf_turbocell_satmode, tvb, 1, 1, FALSE);
        proto_tree_add_item(turbocell_tree, hf_turbocell_nwid, tvb, 1, 1, FALSE);

        /* it seem when we have this magic number,that means an alternate header version */

        if (tvb_get_bits64(tvb, 64,48,FALSE) != G_GINT64_CONSTANT(0x000001fe23dc45ba)){ 
        proto_tree_add_item(turbocell_tree, hf_turbocell_counter, tvb, 0x02, 2, FALSE);
        proto_tree_add_item(turbocell_tree, hf_turbocell_dst, tvb, 0x04, 6, FALSE);
        proto_tree_add_item(turbocell_tree, hf_turbocell_timestamp, tvb, 0x0A, 3, FALSE);

        } else {
        proto_tree_add_item(turbocell_tree, hf_turbocell_timestamp, tvb, 0x02, 3, FALSE);
        proto_tree_add_item(turbocell_tree, hf_turbocell_counter, tvb, 0x05, 3, FALSE);
        proto_tree_add_item(turbocell_tree, hf_turbocell_dst, tvb, 0x08, 6, FALSE);
        }

        proto_tree_add_item(turbocell_tree, hf_turbocell_unknown, tvb, 0x0E, 2, FALSE);
        proto_tree_add_item(turbocell_tree, hf_turbocell_ip, tvb, 0x10, 4, FALSE);


        remaining_length=tvb_length_remaining(tvb, 0x14);

        if (remaining_length > 6) {

            /* If the first character is a printable character that means we have a payload with network info */
            /* I couldn't find anything in the header that would definitvely indicate if payload is either data or network info */
            /* Since the frame size is limited this should work ok */

            if (tvb_get_guint8(tvb, 0x14)>=0x20){
                name_item = proto_tree_add_item(turbocell_tree, hf_turbocell_name, tvb, 0x14, 30, FALSE);
                network_tree = proto_item_add_subtree(name_item, ett_network);

                str_name=tvb_get_ephemeral_stringz(tvb, 0x14, &str_len);
                if (check_col (pinfo->cinfo, COL_INFO) && str_len > 0) 
                    col_append_fstr(pinfo->cinfo, COL_INFO, ", Network=\"%s\"",format_text(str_name, str_len-1));

                while(tvb_get_guint8(tvb, 0x34 + 8*i)==0x00 && (tvb_length_remaining(tvb,0x34 + 8*i) > 6) && (i<32)) {
                    proto_tree_add_item(network_tree, hf_turbocell_station[i], tvb, 0x34+8*i, 6, FALSE);
                    i++;
                }

                /*Couldn't make sense of the apparently random data in the end*/

                next_tvb = tvb_new_subset_remaining(tvb, 0x34 + 8*i);
                call_dissector(data_handle, next_tvb, pinfo, tree);

            } else {

                tvbuff_t *volatile msdu_tvb = NULL,*next_tvb;
                guint32 msdu_offset = 0x04;
                guint16 j = 1;
                guint16 msdu_length;

                proto_item *parent_item;
                proto_tree *mpdu_tree;
                proto_tree *subframe_tree;

                next_tvb = tvb_new_subset(tvb, 0x14, -1, tvb_get_ntohs(tvb, 0x14));
                parent_item = proto_tree_add_protocol_format(tree, proto_aggregate, next_tvb, 0,
                              tvb_reported_length_remaining(next_tvb, 0), "Turbocell Aggregate Frames");
                mpdu_tree = proto_item_add_subtree(parent_item, ett_msdu_aggregation_parent_tree);
                proto_tree_add_item(mpdu_tree, hf_turbocell_aggregate_len, next_tvb, 0x00, 2, FALSE);
                proto_tree_add_item(mpdu_tree, hf_turbocell_aggregate_unknown1, next_tvb, 0x02, 2, FALSE);

                remaining_length=tvb_length_remaining(next_tvb, msdu_offset);

                do {
                    msdu_length = (tvb_get_letohs(next_tvb, msdu_offset) & 0x0FFF);
                    if (msdu_length==0) break;
                    parent_item = proto_tree_add_uint_format(mpdu_tree, hf_turbocell_aggregate_msdu_header_text,
                    next_tvb,msdu_offset, msdu_length + 0x02,j, "A-MSDU Subframe #%u", j);

                    subframe_tree = proto_item_add_subtree(parent_item, ett_msdu_aggregation_subframe_tree);
                    j++;

                    proto_tree_add_uint_format(subframe_tree, hf_turbocell_aggregate_msdu_len, next_tvb, msdu_offset, 2,
                    msdu_length, "MSDU length: %u (0x%04X)", msdu_length,msdu_length);
                    proto_tree_add_item(subframe_tree, hf_turbocell_aggregate_unknown2, next_tvb, msdu_offset+1, 1, FALSE);

                    msdu_offset += 0x02;
                    remaining_length -= 0x02;
                    msdu_tvb = tvb_new_subset(next_tvb, msdu_offset, (msdu_length>remaining_length)?remaining_length:msdu_length, msdu_length);
                    call_dissector(eth_handle, msdu_tvb, pinfo, subframe_tree);
                    msdu_offset += msdu_length;
                    remaining_length -= msdu_length;
                } while (remaining_length > 6);

                if (remaining_length > 2) {
                    next_tvb = tvb_new_subset_remaining(next_tvb, msdu_offset);
                    call_dissector(data_handle, next_tvb, pinfo, tree);
                }
            }
        }
    }
}
Ejemplo n.º 22
0
static void dissect_tftp_message(tftp_conv_info_t *tftp_info,
                                 tvbuff_t *tvb, packet_info *pinfo,
                                 proto_tree *tree)
{
    proto_tree *tftp_tree = NULL;
    proto_item *ti;
    gint        offset    = 0;
    guint16     opcode;
    guint16     bytes;
    guint16     blocknum;
    guint       i1;
    guint16     error;
    tvbuff_t    *data_tvb = NULL;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "TFTP");

    opcode = tvb_get_ntohs(tvb, offset);

    col_add_str(pinfo->cinfo, COL_INFO,
                val_to_str(opcode, tftp_opcode_vals, "Unknown (0x%04x)"));

    if (tree) {
        ti = proto_tree_add_item(tree, proto_tftp, tvb, offset, -1, ENC_NA);
        tftp_tree = proto_item_add_subtree(ti, ett_tftp);

        if (tftp_info->source_file) {
            ti = proto_tree_add_string(tftp_tree, hf_tftp_source_file, tvb,
                                       0, 0, tftp_info->source_file);
            PROTO_ITEM_SET_GENERATED(ti);
        }

        if (tftp_info->destination_file) {
            ti = proto_tree_add_string(tftp_tree, hf_tftp_destination_file, tvb,
                                       0, 0, tftp_info->destination_file);
            PROTO_ITEM_SET_GENERATED(ti);
        }

        proto_tree_add_uint(tftp_tree, hf_tftp_opcode, tvb,
                            offset, 2, opcode);
    }
    offset += 2;

    switch (opcode) {

    case TFTP_RRQ:
        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_source_file,
                            tvb, offset, i1, ENC_ASCII|ENC_NA);

        tftp_info->source_file = tvb_get_string_enc(wmem_file_scope(), tvb, offset, i1, ENC_ASCII);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        offset += i1;

        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_transfer_type,
                            tvb, offset, i1, ENC_ASCII|ENC_NA);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        offset += i1;

        tftp_dissect_options(tvb, pinfo,  offset, tftp_tree,
                             opcode, tftp_info);
        break;

    case TFTP_WRQ:
        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_destination_file,
                            tvb, offset, i1, ENC_ASCII|ENC_NA);

        tftp_info->destination_file =
            tvb_get_string_enc(wmem_file_scope(), tvb, offset, i1, ENC_ASCII);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", File: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        offset += i1;

        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_transfer_type,
                            tvb, offset, i1, ENC_ASCII|ENC_NA);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Transfer type: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        offset += i1;

        tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
                             opcode,  tftp_info);
        break;

    case TFTP_INFO:
        tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
                             opcode,  tftp_info);
        break;

    case TFTP_DATA:
        blocknum = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2,
                            blocknum);

        /* Sequence analysis on blocknums (first pass only) */
        if (!pinfo->fd->flags.visited) {
            if (blocknum > tftp_info->next_block_num) {
                /* There is a gap.  Don't try to recover from this. */
                tftp_info->next_block_num = blocknum + 1;
                tftp_info->blocks_missing = TRUE;
                /* TODO: add info to a result table for showing expert info in later passes */
            }
            else if (blocknum == tftp_info->next_block_num) {
                /* OK, inc what we expect next */
                tftp_info->next_block_num++;
            }
        }
        offset += 2;

        /* Show number of bytes in this block, and whether it is the end of the file */
        bytes = tvb_reported_length_remaining(tvb, offset);
        col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i%s",
                        blocknum,
                        (bytes < tftp_info->blocksize)?" (last)":"" );

        /* Show data in tree */
        if (bytes > 0) {
            data_tvb = tvb_new_subset(tvb, offset, -1, bytes);
            call_dissector(data_handle, data_tvb, pinfo, tree);
        }

        /* If Export Object tap is listening, need to accumulate blocks info list
           to send to tap. But if already know there are blocks missing, there is no
           point in trying. */
        if (have_tap_listener(tftp_eo_tap) && !tftp_info->blocks_missing) {
            file_block_t *block;

            if (blocknum == 1) {
                /* Reset data for this conversation, freeing any accumulated blocks! */
                cleanup_tftp_blocks(tftp_info);
                tftp_info->next_tap_block_num = 1;
            }

            if (blocknum != tftp_info->next_tap_block_num) {
                /* Ignore.  Could be missing frames, or just clicking previous frame */
                return;
            }

            if (bytes > 0) {
                /* Create a block for this block */
                block = (file_block_t*)g_malloc(sizeof(file_block_t));
                block->length = bytes;
                block->data = tvb_memdup(NULL, data_tvb, 0, bytes);

                /* Add to the end of the list (does involve traversing whole list..) */
                tftp_info->block_list = g_slist_append(tftp_info->block_list, block);
                tftp_info->file_length += bytes;

                /* Look for next blocknum next time */
                tftp_info->next_tap_block_num++;
            }

            /* Tap export object only when reach end of file */
            if (bytes < tftp_info->blocksize) {
                tftp_eo_t        *eo_info;

                /* If don't have a filename, won't tap file info */
                if ((tftp_info->source_file == NULL) && (tftp_info->destination_file == NULL)) {
                    cleanup_tftp_blocks(tftp_info);
                    return;
                }

                /* Create the eo_info to pass to the listener */
                eo_info = wmem_new(wmem_packet_scope(), tftp_eo_t);

                /* Set filename */
                if (tftp_info->source_file) {
                    eo_info->filename = g_strdup(tftp_info->source_file);
                }
                else if (tftp_info->destination_file) {
                    eo_info->filename = g_strdup(tftp_info->destination_file);
                }

                /* Send block list, which will be combined and freed at tap. */
                eo_info->payload_len = tftp_info->file_length;
                eo_info->pkt_num = blocknum;
                eo_info->block_list = tftp_info->block_list;

                /* Send to tap */
                tap_queue_packet(tftp_eo_tap, pinfo, eo_info);

                /* Have sent, so forget list of blocks, and only pay attention if we
                   get back to the first block again. */
                tftp_info->block_list = NULL;
                tftp_info->next_tap_block_num = 1;
            }
        }
        break;

    case TFTP_ACK:
        blocknum = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint(tftp_tree, hf_tftp_blocknum, tvb, offset, 2,
                            blocknum);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Block: %i",
                        blocknum);
        break;

    case TFTP_ERROR:
        error = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint(tftp_tree, hf_tftp_error_code, tvb, offset, 2,
                            error);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Code: %s",
                        val_to_str(error, tftp_error_code_vals, "Unknown (%u)"));

        offset += 2;

        i1 = tvb_strsize(tvb, offset);
        proto_tree_add_item(tftp_tree, hf_tftp_error_string, tvb, offset,
                            i1, ENC_ASCII|ENC_NA);

        col_append_fstr(pinfo->cinfo, COL_INFO, ", Message: %s",
                        tvb_format_stringzpad(tvb, offset, i1));

        expert_add_info(pinfo, NULL, &ei_tftp_blocksize_range);
        break;

    case TFTP_OACK:
        tftp_dissect_options(tvb, pinfo, offset, tftp_tree,
                             opcode, tftp_info);
        break;

    default:
        proto_tree_add_text(tftp_tree, tvb, offset, -1,
                            "Data (%d bytes)", tvb_reported_length_remaining(tvb, offset));
        break;

    }

    return;
}
Ejemplo n.º 23
0
static void
dissect_gmr1_dtap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint32 len, offset;
	gmr1_msg_func_t msg_func;
	const gchar *msg_str;
	gint ett_tree;
	int hf_idx;
	proto_item *dtap_item = NULL/*, *pd_item = NULL*/;
	proto_tree *dtap_tree = NULL/*, *pd_tree = NULL*/;
	guint32 oct[2];
	guint8 pd;

	/* Scan init */
	len = tvb_length(tvb);
	offset = 0;

	/* Protocol descriptor */
	oct[0] = tvb_get_guint8(tvb, offset++);

	if ((oct[0] & GMR1_PD_EXT_MSK) == GMR1_PD_EXT_VAL)
		pd = oct[0] & 0xff;
	else
		pd = oct[0] & 0x0f;

	/* HACK: Quick delegation hack to GSM */
	if (pd != GMR1_PD_RR) {
		call_dissector(gsm_dtap_handle, tvb, pinfo, tree);
		return;
	}

	/* Fill up some info */
	col_append_str(pinfo->cinfo, COL_INFO, " (DTAP) ");

	col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ",
		val_to_str(pd, gmr1_pd_short_vals, "Unknown (%u)"));

	/* Get message parameters */
	oct[1] = tvb_get_guint8(tvb, offset);

	gmr1_get_msg_params((gmr1_pd_e)pd, oct[1], &msg_str, &ett_tree, &hf_idx, &msg_func);

	/* Create protocol tree */
	if (msg_str == NULL)
	{
		dtap_item = proto_tree_add_protocol_format(
			tree, proto_gmr1_dtap, tvb, 0, len,
			"GMR-1 DTAP - Message Type (0x%02x)", oct[1]);
		dtap_tree = proto_item_add_subtree(dtap_item, ett_gmr1_dtap);

		col_append_fstr(pinfo->cinfo, COL_INFO, "Message Type (0x%02x) ", oct[1]);
	}
	else
	{
		dtap_item = proto_tree_add_protocol_format(
			tree, proto_gmr1_dtap, tvb, 0, -1,
			"GMR-1 DTAP - %s", msg_str);
		dtap_tree = proto_item_add_subtree(dtap_item, ett_gmr1_dtap);

		col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", msg_str);
	}

	/* Start over */
	offset = 0;

	/* Protocol discriminator item */
	/*pd_item =*/ proto_tree_add_text(
		dtap_tree, tvb, 1, 1,
		"Protocol Discriminator: %s",
		val_to_str(pd, gmr1_pd_vals, "Unknown (%u)")
	);

	/*pd_tree = proto_item_add_subtree(pd_item, ett_gmr1_pd);*/

		/* Move on */
	offset++;

	/* Message type - [1] 11.4 */
	proto_tree_add_uint_format(
		dtap_tree, hf_idx, tvb, offset, 1, oct[1],
		"Message Type: %s", msg_str ? msg_str : "(Unknown)"
	);

	offset++;

	/* Decode elements */
	if (msg_func) {
		(*msg_func)(tvb, dtap_tree, pinfo, offset, len - offset);
	} else {
		proto_tree_add_text(dtap_tree, tvb, offset, len - offset,
		                    "Message Elements");
	}

	/* Done ! */
	return;
}
Ejemplo n.º 24
0
static void
dissect_dvb_data_mpe(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

    guint       offset = 0, tot_len = 0;
    guint8      llc_snap_flag;
    int         i;

    proto_item *ti;
    proto_tree *dvb_data_mpe_tree;
    tvbuff_t   *mac_tvb;
    tvbuff_t   *mac_bytes_tvb[6];
    tvbuff_t   *data_tvb;

    /* The TVB should start right after the section_length in the Section packet */

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "DVB-DATA");
    col_set_str(pinfo->cinfo, COL_INFO, "MultiProtocol Encapsulation");

    ti = proto_tree_add_item(tree, proto_dvb_data_mpe, tvb, offset, -1, ENC_NA);
    dvb_data_mpe_tree = proto_item_add_subtree(ti, ett_dvb_data_mpe);

    offset += packet_mpeg_sect_header(tvb, offset, dvb_data_mpe_tree, &tot_len, NULL);


    /* Parse the DMC-CC private section header */

    mac_bytes_tvb[5] = tvb_new_subset_length(tvb, offset, 1);
    offset += 1;
    mac_bytes_tvb[4] = tvb_new_subset_length(tvb, offset, 1);
    offset += 1;

    proto_tree_add_item(dvb_data_mpe_tree, hf_dvb_data_mpe_reserved,                   tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(dvb_data_mpe_tree, hf_dvb_data_mpe_payload_scrambling_control, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(dvb_data_mpe_tree, hf_dvb_data_mpe_address_scrambling_control, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(dvb_data_mpe_tree, hf_dvb_data_mpe_llc_snap_flag,              tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(dvb_data_mpe_tree, hf_dvb_data_mpe_current_next_indicator,     tvb, offset, 1, ENC_BIG_ENDIAN);
    llc_snap_flag = tvb_get_guint8(tvb, offset) & DVB_DATA_MPE_LLC_SNAP_FLAG_MASK;
    offset += 1;

    proto_tree_add_item(dvb_data_mpe_tree, hf_dvb_data_mpe_section_number,             tvb, offset, 1, ENC_BIG_ENDIAN);
    offset += 1;

    proto_tree_add_item(dvb_data_mpe_tree, hf_dvb_data_mpe_last_section_number,        tvb, offset, 1, ENC_BIG_ENDIAN);
    offset += 1;

    for (i = 3; i >= 0; i--) {
        mac_bytes_tvb[i] = tvb_new_subset_length(tvb, offset, 1);
        offset += 1;
    }

    mac_tvb = tvb_new_composite();

    for (i = 0; i < 6; i++)
        tvb_composite_append(mac_tvb, mac_bytes_tvb[i]);

    tvb_composite_finalize(mac_tvb);

    proto_tree_add_item(dvb_data_mpe_tree, hf_dvb_data_mpe_dst_mac, mac_tvb, 0 , 6, ENC_NA);
    col_add_str(pinfo->cinfo, COL_RES_DL_DST, tvb_ether_to_str(mac_tvb, 0));

    data_tvb = tvb_new_subset_remaining(tvb, offset);

    if (llc_snap_flag) {
        call_dissector(llc_handle, data_tvb, pinfo, tree);
    } else {
        call_dissector(ip_handle, data_tvb, pinfo, tree);
    }

    packet_mpeg_sect_crc(tvb, pinfo, dvb_data_mpe_tree, 0, tot_len - 1);
    return;

}
Ejemplo n.º 25
0
/*
 * Process a multipart body-part:
 *      MIME-part-headers [ line-end *OCTET ]
 *      line-end dashed-boundary transport-padding line-end
 *
 * If applicable, call a media subdissector.
 *
 * Return the offset to the start of the next body-part.
 */
static gint
process_body_part(proto_tree *tree, tvbuff_t *tvb, multipart_info_t *m_info,
                  packet_info *pinfo, gint start, gint idx,
                  gboolean *last_boundary)
{
    proto_tree *subtree;
    proto_item *ti;
    gint offset = start, next_offset = 0;
    char *parameters = NULL;
    gint body_start, boundary_start, boundary_line_len;

    gchar *content_type_str = NULL;
    gchar *content_encoding_str = NULL;
    char *filename = NULL;
    char *mimetypename = NULL;
    int  len = 0;
    gboolean last_field = FALSE;
    gboolean is_raw_data = FALSE;

    const guint8 *boundary = (guint8 *)m_info->boundary;
    gint boundary_len = m_info->boundary_length;

    ti = proto_tree_add_item(tree, hf_multipart_part, tvb, start, 0, ENC_ASCII|ENC_NA);
    subtree = proto_item_add_subtree(ti, ett_multipart_body);

    /* find the next boundary to find the end of this body part */
    boundary_start = find_next_boundary(tvb, offset, boundary, boundary_len,
                                        &boundary_line_len, last_boundary);

    if (boundary_start <= 0) {
        return -1;
    }

    /*
     * Process the MIME-part-headers
     */

    while (!last_field)
    {
        gint colon_offset;
        char *hdr_str;
        char *header_str;

        /* Look for the end of the header (denoted by cr)
         * 3:d argument to imf_find_field_end() maxlen; must be last offset in the tvb.
         */
        next_offset = imf_find_field_end(tvb, offset, tvb_reported_length_remaining(tvb, offset)+offset, &last_field);
        /* the following should never happen */
        /* If cr not found, won't have advanced - get out to avoid infinite loop! */
        /*
        if (next_offset == offset) {
            break;
        }
        */
        if (last_field && (next_offset+2) <= boundary_start) {
            /* Add the extra CRLF of the last field */
            next_offset += 2;
        } else if((next_offset-2) == boundary_start) {
            /* if CRLF is the start of next boundary it belongs to the boundary and not the field,
               so it's the last field without CRLF */
            last_field = TRUE;
            next_offset -= 2;
        } else if (next_offset > boundary_start) {
            /* if there is no CRLF between last field and next boundary - trim it! */
            next_offset = boundary_start;
        }

        hdr_str = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, next_offset - offset, ENC_ASCII);

        header_str = unfold_and_compact_mime_header(hdr_str, &colon_offset);
        if (colon_offset <= 0) {
            /* if there is no colon it's no header, so break and add complete line to the body */
            next_offset = offset;
            break;
        } else {
            gint hf_index;

            /* Split header name from header value */
            header_str[colon_offset] = '\0';
            hf_index = is_known_multipart_header(header_str, colon_offset);

            if (hf_index == -1) {
                if(isprint_string(hdr_str)) {
                    proto_tree_add_format_text(subtree, tvb, offset, next_offset - offset);
                } else {
                    /* if the header name is unkown and not printable, break and add complete line to the body */
                    next_offset = offset;
                    break;
                }
            } else {
                char *value_str = header_str + colon_offset + 1;

                proto_tree_add_string_format(subtree,
                                             hf_header_array[hf_index], tvb,
                                             offset, next_offset - offset,
                                             (const char *)value_str, "%s",
                                             tvb_format_text(tvb, offset, next_offset - offset));

                switch (hf_index) {
                case POS_ORIGINALCONTENT:
                {
                    gint semicolon_offset;
                    /* The Content-Type starts at colon_offset + 1 or after the type parameter */
                    char* type_str = find_parameter(value_str, "type=", NULL);
                    if(type_str != NULL) {
                        value_str = type_str;
                    }

                    semicolon_offset = index_of_char(
                                           value_str, ';');

                    if (semicolon_offset > 0) {
                        value_str[semicolon_offset] = '\0';
                        m_info->orig_parameters = wmem_strdup(wmem_packet_scope(),
                                                              value_str + semicolon_offset + 1);
                    }

                    m_info->orig_content_type = wmem_ascii_strdown(wmem_packet_scope(), value_str, -1);
                }
                break;
                case POS_CONTENT_TYPE:
                {
                    /* The Content-Type starts at colon_offset + 1 */
                    gint semicolon_offset = index_of_char(
                                                value_str, ';');

                    if (semicolon_offset > 0) {
                        value_str[semicolon_offset] = '\0';
                        parameters = wmem_strdup(wmem_packet_scope(), value_str + semicolon_offset + 1);
                    } else {
                        parameters = NULL;
                    }

                    content_type_str = wmem_ascii_strdown(wmem_packet_scope(), value_str, -1);

                    /* Show content-type in root 'part' label */
                    proto_item_append_text(ti, " (%s)", content_type_str);

                    /* find the "name" parameter in case we don't find a content disposition "filename" */
                    if((mimetypename = find_parameter(parameters, "name=", &len)) != NULL) {
                        mimetypename = g_strndup(mimetypename, len);
                    }

                    if(strncmp(content_type_str, "application/octet-stream",
                               sizeof("application/octet-stream")-1) == 0) {
                        is_raw_data = TRUE;
                    }

                    /* there are only 2 body parts possible and each part has specific content types */
                    if(m_info->protocol && idx == 0
                            && (is_raw_data || g_ascii_strncasecmp(content_type_str, m_info->protocol,
                                    strlen(m_info->protocol)) != 0))
                    {
                        return -1;
                    }
                }
                break;
                case POS_CONTENT_TRANSFER_ENCODING:
                {
                    /* The Content-Transferring starts at colon_offset + 1 */
                    gint cr_offset = index_of_char(value_str, '\r');

                    if (cr_offset > 0) {
                        value_str[cr_offset] = '\0';
                    }

                    content_encoding_str = wmem_ascii_strdown(wmem_packet_scope(), value_str, -1);
                }
                break;
                case POS_CONTENT_DISPOSITION:
                {
                    /* find the "filename" parameter */
                    if((filename = find_parameter(value_str, "filename=", &len)) != NULL) {
                        filename = g_strndup(filename, len);
                    }
                }
                break;
                default:
                    break;
                }
            }
        }
        offset = next_offset;
    }

    body_start = next_offset;

    /*
     * Process the body
     */

    {
        gint body_len = boundary_start - body_start;
        tvbuff_t *tmp_tvb = tvb_new_subset_length(tvb, body_start, body_len);
        /* if multipart subtype is encrypted the protcol string was set */
        /* see: https://msdn.microsoft.com/en-us/library/cc251581.aspx */
        /* there are only 2 body parts possible and each part has specific content types */
        if(m_info->protocol && idx == 1 && is_raw_data)
        {
            gssapi_encrypt_info_t  encrypt;

            memset(&encrypt, 0, sizeof(encrypt));
            encrypt.decrypt_gssapi_tvb=DECRYPT_GSSAPI_NORMAL;

            dissect_kerberos_encrypted_message(tmp_tvb, pinfo, subtree, &encrypt);

            if(encrypt.gssapi_decrypted_tvb) {
                tmp_tvb = encrypt.gssapi_decrypted_tvb;
                is_raw_data = FALSE;
                content_type_str = m_info->orig_content_type;
                parameters = m_info->orig_parameters;
            } else if(encrypt.gssapi_encrypted_tvb) {
                tmp_tvb = encrypt.gssapi_encrypted_tvb;
                proto_tree_add_expert(tree, pinfo, &ei_multipart_decryption_not_possible, tmp_tvb, 0, -1);
            }
        }

        if (!is_raw_data &&
                content_type_str) {

            /*
             * subdissection
             */
            gboolean dissected;

            /*
             * Try and remove any content transfer encoding so that each sub-dissector
             * doesn't have to do it itself
             *
             */

            if(content_encoding_str && remove_base64_encoding) {

                if(!g_ascii_strncasecmp(content_encoding_str, "base64", 6))
                    tmp_tvb = base64_decode(pinfo, tmp_tvb, filename ? filename : (mimetypename ? mimetypename : content_type_str));

            }

            /*
             * First try the dedicated multipart dissector table
             */
            dissected = dissector_try_string(multipart_media_subdissector_table,
                                             content_type_str, tmp_tvb, pinfo, subtree, parameters);
            if (! dissected) {
                /*
                 * Fall back to the default media dissector table
                 */
                dissected = dissector_try_string(media_type_dissector_table,
                                                 content_type_str, tmp_tvb, pinfo, subtree, parameters);
            }
            if (! dissected) {
                const char *save_match_string = pinfo->match_string;
                pinfo->match_string = content_type_str;
                call_dissector_with_data(media_handle, tmp_tvb, pinfo, subtree, parameters);
                pinfo->match_string = save_match_string;
            }
            parameters = NULL; /* Shares same memory as content_type_str */
        } else {
            call_dissector(data_handle, tmp_tvb, pinfo, subtree);
        }
        proto_item_set_len(ti, boundary_start - start);
        if (*last_boundary == TRUE) {
            proto_tree_add_item(tree, hf_multipart_last_boundary, tvb, boundary_start, boundary_line_len, ENC_NA|ENC_ASCII);
        } else {
            proto_tree_add_item(tree, hf_multipart_boundary, tvb, boundary_start, boundary_line_len, ENC_NA|ENC_ASCII);
        }

        g_free(filename);
        g_free(mimetypename);

        return boundary_start + boundary_line_len;
    }
}
Ejemplo n.º 26
0
static void
dissect_rtacser_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Set up structures needed to add the protocol subtree and manage it */
    proto_item    *rtacser_item, *ts_item, *cl_item, *data_payload;
    proto_tree    *rtacser_tree, *cl_tree;
    int           offset=0, len=0;
    guint         event_type;
    guint32       timestamp1, timestamp2;
    gboolean      cts, dcd, dsr, rts, dtr, ring, mbok;
    tvbuff_t      *payload_tvb;

    len = RTACSER_HEADER_LEN;

    /* Make entries in Protocol column on summary display */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTAC Serial");
    col_clear(pinfo->cinfo, COL_INFO);

    if (tree) {

        rtacser_item = proto_tree_add_protocol_format(tree, proto_rtacser, tvb, 0, len, "RTAC Serial Line");
        rtacser_tree = proto_item_add_subtree(rtacser_item, ett_rtacser);

        /* Time-stamp is stored as 2 x 32-bit unsigned integers, the left and right-hand side of the decimal point respectively */
        /* The format mirrors the timeval struct - absolute Epoch time (seconds since 1/1/1970) with an added microsecond component */
        timestamp1 = tvb_get_ntohl(tvb, offset);
        timestamp2 = tvb_get_ntohl(tvb, offset+4);
        ts_item = proto_tree_add_item(rtacser_tree, hf_rtacser_timestamp, tvb, offset, 8, ENC_BIG_ENDIAN);
        proto_item_set_text(ts_item, "Arrived At Time: %u.%u" , timestamp1, timestamp2);
        offset += 8;

        /* Set INFO column with RTAC Serial Event Type */
        event_type = tvb_get_guint8(tvb, offset);
        col_clear(pinfo->cinfo, COL_INFO); /* clear out stuff in the info column */
        col_add_fstr(pinfo->cinfo, COL_INFO, "%-21s", val_to_str_const(event_type, rtacser_eventtype_vals, "Unknown Type"));

        /* Add event type to tree */
        proto_tree_add_item(rtacser_tree, hf_rtacser_event_type, tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;

        /* Retrieve EIA-232 serial control line states */
        cts = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_CTS;
        dcd = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_DCD;
        dsr = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_DSR;
        rts = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_RTS;
        dtr = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_DTR;
        ring = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_RING;
        mbok = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_MBOK;

        cl_item = proto_tree_add_text(rtacser_tree, tvb, offset, 1, "Control Lines");
        cl_tree = proto_item_add_subtree(cl_item, ett_rtacser_cl);

        /* Add UART Control Line information to INFO column */
        col_append_str(pinfo->cinfo, COL_INFO, " ( ");
        (cts)  ? col_append_str(pinfo->cinfo, COL_INFO, "CTS") : col_append_str(pinfo->cinfo, COL_INFO, "/CTS");
        (dcd)  ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DCD") : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/DCD");
        (dsr)  ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DSR") : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/DSR");
        (rts)  ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RTS") : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/RTS");
        (dtr)  ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DTR") : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/DTR");
        (ring) ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RING") : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/RING");
        (mbok) ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "MBOK") : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/MBOK");
        col_append_str(pinfo->cinfo, COL_INFO, " )");

        /* Add UART Control Line information to tree */
        proto_item_append_text(cl_item, " (");
        (cts)  ? proto_item_append_text(cl_item, "CTS, ") : proto_item_append_text(cl_item, "/CTS, ");
        (dcd)  ? proto_item_append_text(cl_item, "DCD, ") : proto_item_append_text(cl_item, "/DCD, ");
        (dsr)  ? proto_item_append_text(cl_item, "DSR, ") : proto_item_append_text(cl_item, "/DSR, ");
        (rts)  ? proto_item_append_text(cl_item, "RTS, ") : proto_item_append_text(cl_item, "/RTS, ");
        (dtr)  ? proto_item_append_text(cl_item, "DTR, ") : proto_item_append_text(cl_item, "/DTR, ");
        (ring) ? proto_item_append_text(cl_item, "RING, ") : proto_item_append_text(cl_item, "/RING, ");
        (mbok) ? proto_item_append_text(cl_item, "MBOK") : proto_item_append_text(cl_item, "/MBOK");
        proto_item_append_text(cl_item, ")");

        proto_tree_add_item(cl_tree, hf_rtacser_ctrl_cts, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(cl_tree, hf_rtacser_ctrl_dcd, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(cl_tree, hf_rtacser_ctrl_dsr, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(cl_tree, hf_rtacser_ctrl_rts, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(cl_tree, hf_rtacser_ctrl_dtr, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(cl_tree, hf_rtacser_ctrl_ring, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(cl_tree, hf_rtacser_ctrl_mbok, tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;

        /* 2-byte footer */
        proto_tree_add_item(rtacser_tree, hf_rtacser_footer, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;

        /* If no payload dissector has been selected, indicate to the user the preferences options */
        if ((tvb_reported_length_remaining(tvb, offset) > 0) && (global_rtacser_payload_proto == RTACSER_PAYLOAD_NONE)) {
            data_payload = proto_tree_add_item(tree, hf_rtacser_data, tvb, offset, -1, ENC_NA);
            proto_item_set_text(data_payload,"Payload Protocol not selected.  Check 'Preferences-> Protocols-> RTAC Serial' for options");
            return;
        }

    } /* tree */

    /* Determine correct message type and call appropriate dissector */
    if (tvb_reported_length_remaining(tvb, RTACSER_HEADER_LEN) > 0) {

        switch (global_rtacser_payload_proto) {
            case RTACSER_PAYLOAD_SELFM:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(selfm_handle, payload_tvb, pinfo, tree);
                break;
            case RTACSER_PAYLOAD_DNP3:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(dnp3_handle, payload_tvb, pinfo, tree);
                break;
            case RTACSER_PAYLOAD_MODBUS:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(modbus_handle, payload_tvb, pinfo, tree);
                break;
            case RTACSER_PAYLOAD_SYNPHASOR:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(synphasor_handle, payload_tvb, pinfo, tree);
                break;
            default:
                break;
        }
    }

}
Ejemplo n.º 27
0
/*
 * Main dissection routine.
 */
static gboolean
dissect_iwarp_mpa(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
	tvbuff_t *next_tvb = NULL;
	conversation_t *conversation = NULL;
	mpa_state_t *state = NULL;
	struct tcpinfo *tcpinfo;
	guint8 endpoint = 3;
	guint16 ulpdu_length = 0;

	if (data == NULL)
		return FALSE;
	tcpinfo = (struct tcpinfo *)data;

	/* FPDU */
	if (tvb_length(tvb) >= MPA_SMALLEST_FPDU_LEN && is_mpa_fpdu(pinfo)) {

		conversation = find_conversation(pinfo->fd->num, &pinfo->src,
				&pinfo->dst, pinfo->ptype, pinfo->srcport, pinfo->destport, 0);

		state = get_mpa_state(conversation);

		if (pinfo->srcport == state->minfo[MPA_INITIATOR].port) {
			endpoint = MPA_INITIATOR;
		} else if (pinfo->srcport == state->minfo[MPA_RESPONDER].port) {
			endpoint = MPA_RESPONDER;
		} else {
			REPORT_DISSECTOR_BUG("endpoint cannot be determined");
		}

		/* Markers are used by either the Initiator or the Responder or both. */
		if ((state->ini_exp_m_res || state->res_exp_m_ini) && endpoint <= MPA_RESPONDER) {

			/* find the TCP sequence number of the first FPDU */
			if (!state->minfo[endpoint].valid) {
				state->minfo[endpoint].seq = tcpinfo->seq;
				state->minfo[endpoint].valid = TRUE;
			}
		}

		/* dissect FPDU */
		ulpdu_length = dissect_mpa_fpdu(tvb, pinfo, tree, state, tcpinfo,
				endpoint);

		/* an ulpdu_length of 0 should never happen */
		if (!ulpdu_length)
			return FALSE;

		/* removes Markers if any and prepares new tvbuff for next dissector */
		if (endpoint <= MPA_RESPONDER && state->minfo[endpoint].valid
				&& number_of_markers(state, tcpinfo, endpoint) > 0) {
			next_tvb = tvb_new_subset(remove_markers(tvb, pinfo,
					get_first_marker_offset(state, tcpinfo, endpoint),
					number_of_markers(state, tcpinfo, endpoint),
					fpdu_total_length(tcpinfo)), MPA_ULPDU_LENGTH_LEN,
					ulpdu_length, ulpdu_length);
		} else {
			next_tvb = tvb_new_subset(tvb, MPA_ULPDU_LENGTH_LEN, ulpdu_length,
					ulpdu_length);
		}


		/* call subdissector */
		if (ddp_rdmap_handle) {
			call_dissector(ddp_rdmap_handle, next_tvb, pinfo, tree);
		} else {
			REPORT_DISSECTOR_BUG("ddp_handle was null");
		}

		return TRUE;
	}

	/* MPA REQUEST or MPA REPLY */
	if (tvb_length(tvb) >= MPA_REQ_REP_FRAME_HEADER_LEN) {
		if (is_mpa_req(tvb, pinfo))
			return dissect_mpa_req_rep(tvb, pinfo, tree, MPA_REQUEST_FRAME);
		else if (is_mpa_rep(tvb, pinfo))
			return dissect_mpa_req_rep(tvb, pinfo, tree, MPA_REPLY_FRAME);
	}
	return FALSE;
}
Ejemplo n.º 28
0
static void
dissect_bacnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item *ti;
    proto_item *ct;
    proto_tree *bacnet_tree;
    proto_tree *control_tree;

    gint offset;
    guint8 bacnet_version;
    guint8 bacnet_control;
    guint8 bacnet_dlen;
    guint8 bacnet_slen;
    guint8 bacnet_mesgtyp;
    guint8 bacnet_rejectreason;
    guint8 bacnet_rportnum;
    guint8 bacnet_pinfolen;
    guint8 i;
    guint8 j;
    tvbuff_t *next_tvb;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-NPDU");

    col_set_str(pinfo->cinfo, COL_INFO, "Building Automation and Control Network NPDU");

    offset = 0;
    bacnet_version = tvb_get_guint8(tvb, offset);
    bacnet_control = tvb_get_guint8(tvb, offset+1);
    bacnet_dlen = 0;
    bacnet_slen = 0;
    bacnet_mesgtyp = 0;
    bacnet_rejectreason = 0;
    bacnet_rportnum = 0;
    bacnet_pinfolen =0;
    i = 0;
    j = 0;

    /* I don't know the length of the NPDU by now. Setting the length after dissection */
    ti = proto_tree_add_item(tree, proto_bacnet, tvb, 0, -1, FALSE);

    bacnet_tree = proto_item_add_subtree(ti, ett_bacnet);

    proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_version, tvb,
                                     offset, 1,
                                     bacnet_version,"0x%02x (%s)",bacnet_version,
                                     (bacnet_version == 0x01)?"ASHRAE 135-1995":"unknown");
    offset ++;
    ct = proto_tree_add_uint(bacnet_tree, hf_bacnet_control,
                             tvb, offset, 1, bacnet_control);
    control_tree = proto_item_add_subtree(ct, ett_bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_net,
                           tvb, offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_res1, tvb,
                           offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_dest, tvb,
                           offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_res2, tvb,
                           offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_src, tvb,
                           offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_expect, tvb,
                           offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_high,
                           tvb, offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_low,
                           tvb, offset, 1, bacnet_control);
    offset ++;
    if (bacnet_control & BAC_CONTROL_DEST) { /* DNET, DLEN, DADR */
        proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                            tvb, offset, 2, FALSE);
        offset += 2;
        bacnet_dlen = tvb_get_guint8(tvb, offset);
        /* DLEN = 0 is broadcast on dest.network */
        if( bacnet_dlen == 0) {
            /* append to hf_bacnet_dlen: broadcast */
            proto_tree_add_uint_format_value(bacnet_tree,
                                             hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen,
                                             "%d indicates Broadcast on Destination Network",
                                             bacnet_dlen);
            offset ++;
            /* going to SNET */
        } else if (bacnet_dlen==6) {
            proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen,
                                tvb, offset, 1, bacnet_dlen);
            offset ++;
            /* Ethernet MAC */
            proto_tree_add_item(bacnet_tree,
                                hf_bacnet_dadr_eth, tvb, offset,
                                bacnet_dlen, FALSE);
            offset += bacnet_dlen;
        } else if (bacnet_dlen==1) {
            proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen,
                                tvb, offset, 1, bacnet_dlen);
            offset ++;
            /* MS/TP or ARCNET MAC */
            proto_tree_add_item(bacnet_tree,
                                hf_bacnet_dadr_mstp, tvb, offset,
                                bacnet_dlen, FALSE);
            offset += bacnet_dlen;
        } else if (bacnet_dlen<7) {
            proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen,
                                tvb, offset, 1, bacnet_dlen);
            offset ++;
            /* Other MAC formats should be included here */
            proto_tree_add_item(bacnet_tree,
                                hf_bacnet_dadr_tmp, tvb, offset,
                                bacnet_dlen, FALSE);
            offset += bacnet_dlen;
        } else {
            proto_tree_add_uint_format_value(bacnet_tree,
                                             hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen,
                                             "%d invalid!",
                                             bacnet_dlen);
        }
    }
    if (bacnet_control & BAC_CONTROL_SRC) { /* SNET, SLEN, SADR */
        /* SNET */
        proto_tree_add_uint(bacnet_tree, hf_bacnet_snet,
                            tvb, offset, 2, tvb_get_ntohs(tvb, offset));
        offset += 2;
        bacnet_slen = tvb_get_guint8(tvb, offset);
        if( bacnet_slen == 0) { /* SLEN = 0 invalid */
            proto_tree_add_uint_format_value(bacnet_tree,
                                             hf_bacnet_slen, tvb, offset, 1, bacnet_slen,
                                             "%d invalid!",
                                             bacnet_slen);
            offset ++;
        } else if (bacnet_slen==6) {
            /* SLEN */
            proto_tree_add_uint(bacnet_tree, hf_bacnet_slen,
                                tvb, offset, 1, bacnet_slen);
            offset ++;
            /* Ethernet MAC */
            proto_tree_add_item(bacnet_tree,
                                hf_bacnet_sadr_eth, tvb, offset,
                                bacnet_slen, FALSE);
            offset += bacnet_slen;
        } else if (bacnet_slen==1) {
            /* SLEN */
            proto_tree_add_uint(bacnet_tree, hf_bacnet_slen,
                                tvb, offset, 1, bacnet_slen);
            offset ++;
            /* MS/TP or ARCNET MAC */
            proto_tree_add_item(bacnet_tree,
                                hf_bacnet_sadr_mstp, tvb, offset,
                                bacnet_slen, FALSE);
            offset += bacnet_slen;
        } else if (bacnet_slen<6) { /* LON MAC */
            /* SLEN */
            proto_tree_add_uint(bacnet_tree, hf_bacnet_slen,
                                tvb, offset, 1, bacnet_slen);
            offset ++;
            /* Other MAC formats should be included here */
            proto_tree_add_item(bacnet_tree,
                                hf_bacnet_sadr_tmp, tvb, offset,
                                bacnet_slen, FALSE);
            offset += bacnet_slen;
        } else {
            proto_tree_add_uint_format_value(bacnet_tree,
                                             hf_bacnet_slen, tvb, offset, 1, bacnet_slen,
                                             "%d invalid!",
                                             bacnet_slen);
            offset ++;
        }
    }
    if (bacnet_control & BAC_CONTROL_DEST) { /* Hopcount */
        proto_tree_add_item(bacnet_tree, hf_bacnet_hopc,
                            tvb, offset, 1, FALSE);
        offset ++;
    }
    /* Network Layer Message Type */
    if (bacnet_control & BAC_CONTROL_NET) {
        bacnet_mesgtyp =  tvb_get_guint8(tvb, offset);
        proto_tree_add_uint_format_value(bacnet_tree,
                                         hf_bacnet_mesgtyp, tvb, offset, 1, bacnet_mesgtyp,
                                         "%02x (%s)", bacnet_mesgtyp,
                                         bacnet_mesgtyp_name(bacnet_mesgtyp));
        /* Put the NPDU Type in the info column */
        if (check_col(pinfo->cinfo, COL_INFO))
        {
            col_clear(pinfo->cinfo, COL_INFO);
            col_add_str(pinfo->cinfo, COL_INFO,
                        bacnet_mesgtyp_name(bacnet_mesgtyp));
        }
        offset ++;
        /* Vendor ID
        * The standard says: "If Bit 7 of the control octet is 1 and
        * the Message Type field contains a value in the range
        * X'80' - X'FF', then a Vendor ID field shall be present (...)."
        * We should not go any further in dissecting the packet if it's
        * not present, but we don't know about that: No length field...
        */
        if (bacnet_mesgtyp > 0x7f) {
            proto_tree_add_item(bacnet_tree, hf_bacnet_vendor,
                                tvb, offset, 2, FALSE);
            offset += 2;
            /* attention: doesnt work here because of if(tree) */
            call_dissector(data_handle,
                           tvb_new_subset_remaining(tvb, offset), pinfo, tree);
        }
        /* Performance Index (in I-Could-Be-Router-To-Network) */
        if (bacnet_mesgtyp == BAC_NET_ICB_R) {
            proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                                tvb, offset, 2, FALSE);
            offset += 2;
            proto_tree_add_item(bacnet_tree, hf_bacnet_perf,
                                tvb, offset, 1, FALSE);
            offset ++;
        }
        /* Reason, DNET (in Reject-Message-To-Network) */
        if (bacnet_mesgtyp == BAC_NET_REJ) {
            bacnet_rejectreason = tvb_get_guint8(tvb, offset);
            proto_tree_add_uint_format_value(bacnet_tree,
                                             hf_bacnet_rejectreason,
                                             tvb, offset, 1,
                                             bacnet_rejectreason, "%d (%s)",
                                             bacnet_rejectreason,
                                             bacnet_rejectreason_name(bacnet_rejectreason));
            offset ++;
            proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                                tvb, offset, 2, FALSE);
            offset += 2;
        }
        /* N*DNET (in Router-Busy-To-Network,Router-Available-To-Network) */
        if ((bacnet_mesgtyp == BAC_NET_R_BUSY) ||
                (bacnet_mesgtyp == BAC_NET_WHO_R) ||
                (bacnet_mesgtyp == BAC_NET_R_AVA) ||
                (bacnet_mesgtyp == BAC_NET_IAM_R) ) {
            while(tvb_reported_length_remaining(tvb, offset) > 1 ) {
                proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                                    tvb, offset, 2, FALSE);
                offset += 2;
            }
        }
        /* Initialize-Routing-Table */
        if ( (bacnet_mesgtyp == BAC_NET_INIT_RTAB) ||
                (bacnet_mesgtyp == BAC_NET_INIT_RTAB_ACK) ) {
            bacnet_rportnum = tvb_get_guint8(tvb, offset);
            /* number of ports */
            proto_tree_add_uint(bacnet_tree, hf_bacnet_rportnum,
                                tvb, offset, 1, bacnet_rportnum);
            offset ++;
            for(i=0; i<bacnet_rportnum; i++) {
                /* Connected DNET */
                proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                                    tvb, offset, 2, FALSE);
                offset += 2;
                /* Port ID */
                proto_tree_add_item(bacnet_tree, hf_bacnet_portid,
                                    tvb, offset, 1, FALSE);
                offset ++;
                /* Port Info Length */
                bacnet_pinfolen = tvb_get_guint8(tvb, offset);
                proto_tree_add_uint(bacnet_tree, hf_bacnet_pinfolen,
                                    tvb, offset, 1, bacnet_pinfolen);
                offset ++;
                proto_tree_add_text(bacnet_tree, tvb, offset,
                                    bacnet_pinfolen, "Port Info: %s",
                                    tvb_bytes_to_str(tvb, offset, bacnet_pinfolen));
                offset += bacnet_pinfolen;
            }
        }
        /* Establish-Connection-To-Network */
        if (bacnet_mesgtyp == BAC_NET_EST_CON) {
            proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                                tvb, offset, 2, FALSE);
            offset += 2;
            proto_tree_add_item(bacnet_tree, hf_bacnet_term_time_value,
                                tvb, offset, 1, FALSE);
            offset ++;
        }
        /* Disconnect-Connection-To-Network */
        if (bacnet_mesgtyp == BAC_NET_DISC_CON) {
            proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                                tvb, offset, 2, FALSE);
            offset += 2;
        }
        proto_item_set_len(ti, offset);
    }
    /* dissect BACnet APDU */
    next_tvb = tvb_new_subset_remaining(tvb,offset);
    if (bacnet_control & BAC_CONTROL_NET) {
        /* Unknown function - dissect the payload as data */
        call_dissector(data_handle, next_tvb, pinfo, tree);
    } else {
        /* APDU - call the APDU dissector */
        call_dissector(bacapp_handle, next_tvb, pinfo, tree);
    }
}
Ejemplo n.º 29
0
static void
dissect_lapb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree          *lapb_tree, *ti;
    guint16             control;
    int                 is_response;
    guint8              byte0;
    tvbuff_t            *next_tvb;

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

    switch (pinfo->p2p_dir) {

    case P2P_DIR_SENT:
        col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DTE");
        col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DCE");
        break;

    case P2P_DIR_RECV:
        col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "DCE");
        col_set_str(pinfo->cinfo, COL_RES_DL_DST, "DTE");
        break;

    default:
        col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A");
        col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A");
        break;
    }

    byte0 = tvb_get_guint8(tvb, 0);

    if (byte0 != 0x01 && byte0 != 0x03 && byte0 != 0x07 && byte0 != 0x0f) /* invalid LAPB frame */
    {
        col_set_str(pinfo->cinfo, COL_INFO, "Invalid LAPB frame");
        if (tree)
            proto_tree_add_protocol_format(tree, proto_lapb, tvb, 0, -1,
                            "Invalid LAPB frame");
        return;
    }

    switch (pinfo->p2p_dir) {

    case P2P_DIR_SENT:
        if (byte0 == 0x03)
            is_response = TRUE;
        else
            is_response = FALSE;
        break;

    case P2P_DIR_RECV:
        if (byte0 == 0x01)
            is_response = TRUE;
        else
            is_response = FALSE;
        break;

    default:
        /*
         * XXX - should we base this on the source and destination
         * addresses?  The problem is that we can tell one direction
         * from another with that, but we can't say which is DTE->DCE
         * and which is DCE->DTE.
         */
        is_response = FALSE;
        break;
    }

    ti = proto_tree_add_protocol_format(tree, proto_lapb, tvb, 0, 2,
                                        "LAPB");
    lapb_tree = proto_item_add_subtree(ti, ett_lapb);
    proto_tree_add_uint(lapb_tree, hf_lapb_address, tvb, 0, 1, byte0);

    control = dissect_xdlc_control(tvb, 1, pinfo, lapb_tree, hf_lapb_control,
            ett_lapb_control, &lapb_cf_items, NULL, NULL, NULL,
            is_response, FALSE, FALSE);

    /* information frame ==> X.25 */
    if (XDLC_IS_INFORMATION(control)) {
        next_tvb = tvb_new_subset_remaining(tvb, 2);
        switch (pinfo->p2p_dir) {

        case P2P_DIR_SENT:
        case P2P_DIR_RECV:
            call_dissector(x25_dir_handle, next_tvb, pinfo, tree);
            break;

        default:
            call_dissector(x25_handle, next_tvb, pinfo, tree);
            break;
        }
    }
}
Ejemplo n.º 30
0
static void
dissect_pw_fr( tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree )
{
	gint packet_size;
	gint payload_size;
	gint payload_padding;
	const int encaps_size = 4; /*encapsulation consists of mandatory CW only*/
	enum {
		PQ_CW_BAD				= 0x001
		    ,PQ_CW_BAD_BITS03 			= 0x002
		    ,PQ_CW_BAD_LEN_GT_PACKET		= 0x004
		    ,PQ_CW_BAD_LEN_MUST_BE_ZERO		= 0x008
		    ,PQ_CW_BAD_LEN_MUST_BE_NONZERO	= 0x010
		,PQ_PAYLOAD_SIZE_ZERO			= 0x020
	} packet_quality;
	
	packet_size = tvb_reported_length_remaining(tvb, 0);
	if (packet_size < encaps_size)
	{
		if (tree)
		{
			proto_item  *item;
			item = proto_tree_add_item(tree, proto_encaps, tvb, 0, -1, FALSE); 
			expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
				"PW packet (%d) is smaller than PW encapsulation header (%d)"
				,(int)packet_size,(int)encaps_size);
		}
		col_set_str(pinfo->cinfo, COL_PROTOCOL, "FR PW");
		col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet < PW encapsulation header");
		return;
	}

	if (dissect_try_cw_first_nibble(tvb,pinfo,tree))
	{
		return;
	}

	/* check how "good" is this packet */   
	/* also decide payload length from packet size and CW */
	packet_quality = 0;
	if (0 != (tvb_get_guint8(tvb, 0) & 0xf0 /*bits03*/))
	{
		packet_quality |= PQ_CW_BAD + PQ_CW_BAD_BITS03;
	}
	{
		/* RFC4619:
		 * [ If the frame's length (defined as the
		 * length of the layer 2 payload plus the length of the control word)
		 * is less than 64 octets, the length field MUST be set to the PW
		 * payload length.  Otherwise, the length field MUST be set to zero. ] 
		 * 
		 * Note difference from RFC4385 which states that:  
		 * [..the length field MUST be set to the length of the PW payload 
		 * *plus* the length of the *PWMCW*. ]
		 */
		int cw_len;
		gint payload_size_packet; /*derived from packet size*/

		cw_len = tvb_get_guint8(tvb, 1) & 0x3f; 
		payload_size_packet = packet_size - encaps_size;
		
		/* 
		 * Initial assumptions.
		 */
		payload_size = payload_size_packet; 
		payload_padding = 0;  
		
		if (payload_size_packet < 64)
		{
			gint payload_size_cw; /*derived from cw*/
			payload_size_cw = cw_len; /*RFC4619-specific*/ 
			if (payload_size_cw == 0)
			{
				packet_quality |= PQ_CW_BAD + PQ_CW_BAD_LEN_MUST_BE_NONZERO;
			}
			else if (payload_size_cw > payload_size_packet)
			{
				packet_quality |= PQ_CW_BAD + PQ_CW_BAD_LEN_GT_PACKET;
			}
			else /* ok */
			{
				payload_size = payload_size_cw;
				payload_padding = payload_size_packet - payload_size_cw; /* >=0 */
			}
		}
		else /* payload_size_packet >= 64 */
		{          
			if (cw_len != 0)
			{
				packet_quality |= PQ_CW_BAD + PQ_CW_BAD_LEN_MUST_BE_ZERO;
			}
		}
	}
	if ((payload_size == 0))
	{		
		packet_quality |= PQ_PAYLOAD_SIZE_ZERO;
	}

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "FR PW");  
	if (check_col(pinfo->cinfo, COL_INFO))
	{
		col_clear(pinfo->cinfo, COL_INFO);
		if (packet_quality & PQ_CW_BAD) 
		{
			col_append_str(pinfo->cinfo, COL_INFO, "CW:Malformed, ");
		}
		col_append_fstr(pinfo->cinfo, COL_INFO, "%d payload octets", (int)payload_size);
	
		if (payload_padding != 0)
		{
			col_append_fstr(pinfo->cinfo, COL_INFO, ", %d padding", (int)payload_padding);
		}
	}

	if (tree)
	{
		proto_tree* subtree;
		proto_item* item_headline;
		proto_item* item;
		
		item_headline = proto_tree_add_item(tree, proto_encaps, tvb, 0, 4, FALSE); 
		proto_item_append_text(item_headline, ": 0x%.8" G_GINT32_MODIFIER "x", tvb_get_ntohl(tvb, 0));
		subtree = proto_item_add_subtree(item_headline, ett_encaps);
		
		if (packet_quality & PQ_CW_BAD_BITS03) /*display only if value is wrong*/
		{
			item = proto_tree_add_item(subtree, hf_cw_bits03, tvb, 0, 1, FALSE);
			expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
				"Bits 0..3 of Control Word must be 0");
		}
		
		(void)proto_tree_add_item( subtree, hf_cw_fecn, tvb, 0, 1, FALSE );
		(void)proto_tree_add_item( subtree, hf_cw_becn, tvb, 0, 1, FALSE );
		(void)proto_tree_add_item( subtree, hf_cw_de, tvb, 0, 1, FALSE );
		(void)proto_tree_add_item( subtree, hf_cw_cr, tvb, 0, 1, FALSE );
		(void)proto_tree_add_item( subtree, hf_cw_frg, tvb, 1, 1, FALSE );
		
		item = proto_tree_add_item( subtree, hf_cw_len, tvb, 1, 1, FALSE );
		if (packet_quality & PQ_CW_BAD_LEN_GT_PACKET)
		{
			expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
				"Bad Length: greater than FR payload size (%d)", 
				(int)payload_size);
		}  
		if (packet_quality & PQ_CW_BAD_LEN_MUST_BE_NONZERO)
		{
			expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
				"Bad Length: must be non-zero if FR PW packet size (%d) is < 64",
				(int)(payload_size+encaps_size));
		}
		if (packet_quality & PQ_CW_BAD_LEN_MUST_BE_ZERO)
		{
			expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
				"Bad Length: must be 0 if FR PW packet size (%d) is >= 64",
				(int)(payload_size+encaps_size));
		}
		
		proto_tree_add_item( subtree, hf_cw_seq, tvb, 2, 2, FALSE );

		if (payload_padding > 0)
		{
			proto_tree_add_text(subtree, tvb, 
				encaps_size+payload_size, payload_padding, 
				"[Padding: %d octets]",(int)payload_padding);
		}               

		if (packet_quality & PQ_PAYLOAD_SIZE_ZERO)
		{
			expert_add_info_format(pinfo, item_headline, PI_MALFORMED, PI_WARN,
				"FR payload size must be non-zero");
		}

	}
	if (payload_size > 0)
	{
		tvbuff_t *tvb_payload;
		tvb_payload = tvb_new_subset(tvb, encaps_size, payload_size, payload_size);
		call_dissector( fr_stripped_address_handle, tvb_payload, pinfo, tree );
	} 
	return;
}