コード例 #1
0
ファイル: packet-ldss.c プロジェクト: crondaemon/wireshark
/* Transfers happen in response to broadcasts, they are always TCP and are
 * used to send the file to the port mentioned in the broadcast. There are
 * 2 types of transfers: Pushes, which are direct responses to searches,
 * in which the peer that has the file connects to the peer that doesn't and
 * sends it, then disconnects. The other type of transfer is a pull, where
 * the peer that doesn't have the file connects to the peer that does and
 * requests it be sent.
 *
 * Pulls have a file request which identifies the desired file,
 * while pushes simply send the file. In practice this works because every
 * file the implementation sends searches for is on a different TCP port
 * on the searcher's machine. */
static int
dissect_ldss_transfer (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
	conversation_t *transfer_conv;
	ldss_transfer_info_t *transfer_info;
	struct tcpinfo *transfer_tcpinfo;
	proto_tree *ti, *line_tree = NULL, *ldss_tree = NULL;
	nstime_t broadcast_response_time;

	/* Reject the packet if data is NULL */
	if (data == NULL)
		return 0;
	transfer_tcpinfo = (struct tcpinfo *)data;

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

	/* Look for the transfer conversation; this was created during
	 * earlier broadcast dissection (see prepare_ldss_transfer_conv) */
	transfer_conv = find_conversation (pinfo->num, &pinfo->src, &pinfo->dst,
					   PT_TCP, pinfo->srcport, pinfo->destport, 0);
	DISSECTOR_ASSERT(transfer_conv);
	transfer_info = (ldss_transfer_info_t *)conversation_get_proto_data(transfer_conv, proto_ldss);
	DISSECTOR_ASSERT(transfer_info);

	/* For a pull, the first packet in the TCP connection is the file request.
	 * First packet is identified by relative seq/ack numbers of 1.
	 * File request only appears on a pull (triggered by an offer - see above
	 * about broadcasts) */
	if (transfer_tcpinfo->seq == 1 &&
	    transfer_tcpinfo->lastackseq == 1 &&
	    transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND) {
		/* LDSS pull transfers look a lot like HTTP.
		 * Sample request:
		 * md5:01234567890123...
		 * Size: 2550
		 * Start: 0
		 * Compression: 0
		 * (remote end sends the file identified by the digest) */
		guint offset = 0;
		gboolean already_dissected = TRUE;

		col_set_str(pinfo->cinfo, COL_INFO, "LDSS File Transfer (Requesting file - pull)");

		if (highest_num_seen == 0 ||
		    highest_num_seen < pinfo->num) {

			already_dissected = FALSE;
			transfer_info->req = wmem_new0(wmem_file_scope(), ldss_file_request_t);
			transfer_info->req->file = wmem_new0(wmem_file_scope(), ldss_file_t);
			highest_num_seen = pinfo->num;
		}

		ti = proto_tree_add_item(tree, proto_ldss,
				tvb, 0, tvb_reported_length(tvb), ENC_NA);
		ldss_tree = proto_item_add_subtree(ti, ett_ldss_transfer);

		/* Populate digest data into the file struct in the request */
		transfer_info->file = transfer_info->req->file;

		/* Grab each line from the packet, there should be 4 but lets
		 * not walk off the end looking for more. */
		while (tvb_offset_exists(tvb, offset)) {
			gint next_offset;
			const guint8 *line;
			int linelen;
			gboolean is_digest_line;
			guint digest_type_len;

			linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);

			/* Include new-line in line */
			line = (guint8 *)tvb_memdup(wmem_packet_scope(), tvb, offset, linelen+1); /* XXX - memory leak? */

			line_tree = proto_tree_add_subtree(ldss_tree, tvb, offset, linelen,
							 ett_ldss_transfer_req, NULL,
							 tvb_format_text(tvb, offset, next_offset-offset));

			/* Reduce code duplication processing digest lines.
			 * There are too many locals to pass to a function - the signature
			 * looked pretty ugly when I tried! */
			is_digest_line = FALSE;

			if (strncmp(line,"md5:",4)==0) {
				is_digest_line = TRUE;
				digest_type_len = 4;
				transfer_info->file->digest_type = DIGEST_TYPE_MD5;
			}
			else if (strncmp(line, "sha1:", 5)==0) {
				is_digest_line = TRUE;
				digest_type_len = 5;
				transfer_info->file->digest_type = DIGEST_TYPE_SHA1;
			}
			else if (strncmp(line, "sha256:", 7)==0) {
				is_digest_line = TRUE;
				digest_type_len = 7;
				transfer_info->file->digest_type = DIGEST_TYPE_SHA256;
			}
			else if (strncmp(line, "unknown:", 8)==0) {
				is_digest_line = TRUE;
				digest_type_len = 8;
				transfer_info->file->digest_type = DIGEST_TYPE_UNKNOWN;
			}
			else if (strncmp(line, "Size: ", 6)==0) {
				/* Sample size line:
				 * Size: 2550\n */
				transfer_info->req->size = g_ascii_strtoull(line+6, NULL, 10);
				ti = proto_tree_add_uint64(line_tree, hf_ldss_size,
						tvb, offset+6, linelen-6, transfer_info->req->size);
				PROTO_ITEM_SET_GENERATED(ti);
			}
			else if (strncmp(line, "Start: ", 7)==0) {
				/* Sample offset line:
				 * Start: 0\n */
				transfer_info->req->offset = g_ascii_strtoull(line+7, NULL, 10);
				ti = proto_tree_add_uint64(line_tree, hf_ldss_offset,
						tvb, offset+7, linelen-7, transfer_info->req->offset);
				PROTO_ITEM_SET_GENERATED(ti);
			}
			else if (strncmp(line, "Compression: ", 13)==0) {
				/* Sample compression line:
				 * Compression: 0\n */
				transfer_info->req->compression = (gint8)strtol(line+13, NULL, 10); /* XXX - bad cast */
				ti = proto_tree_add_uint(line_tree, hf_ldss_compression,
						tvb, offset+13, linelen-13, transfer_info->req->compression);
				PROTO_ITEM_SET_GENERATED(ti);
			}
			else {
				proto_tree_add_expert(line_tree, pinfo, &ei_ldss_unrecognized_line, tvb, offset, linelen);
			}

			if (is_digest_line) {
				proto_item *tii = NULL;

				/* Sample digest-type/digest line:
				 * md5:0123456789ABCDEF\n */
				if (!already_dissected) {
					GByteArray *digest_bytes;

					digest_bytes = g_byte_array_new();
					hex_str_to_bytes(
							tvb_get_ptr(tvb, offset+digest_type_len, linelen-digest_type_len),
							digest_bytes, FALSE);

					if(digest_bytes->len >= DIGEST_LEN)
						digest_bytes->len = (DIGEST_LEN-1);
					/* Ensure the digest is zero-padded */
					transfer_info->file->digest = (guint8 *)wmem_alloc0(wmem_file_scope(), DIGEST_LEN);
					memcpy(transfer_info->file->digest, digest_bytes->data, digest_bytes->len);

					g_byte_array_free(digest_bytes, TRUE);
				}

				tii = proto_tree_add_uint(line_tree, hf_ldss_digest_type,
						tvb, offset, digest_type_len, transfer_info->file->digest_type);
				PROTO_ITEM_SET_GENERATED(tii);
				tii = proto_tree_add_bytes(line_tree, hf_ldss_digest,
						tvb, offset+digest_type_len, MIN(linelen-digest_type_len, DIGEST_LEN),
						transfer_info->file->digest);
				PROTO_ITEM_SET_GENERATED(tii);
			}

			offset = next_offset;
		}

		/* Link forwards to the response for this pull. */
		if (transfer_info->resp_num != 0) {
			ti = proto_tree_add_uint(ldss_tree, hf_ldss_response_in,
						 tvb, 0, 0, transfer_info->resp_num);
			PROTO_ITEM_SET_GENERATED(ti);
		}

		transfer_info->req->num = pinfo->num;
		transfer_info->req->ts = pinfo->abs_ts;
	}
	/* Remaining packets are the file response */
	else {
		guint64 size;
		guint64 offset;
		guint8 compression;

		/* size, digest, compression come from the file request for a pull but
		 * they come from the broadcast for a push. Pushes don't bother
		 * with a file request - they just send the data. We have to get file
		 * info from the offer broadcast which triggered this transfer.
		 * If we cannot find the file request, default to the broadcast. */
		if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND &&
		    transfer_info->req != NULL) {
			transfer_info->file = transfer_info->req->file;
			size = transfer_info->req->size;
			offset = transfer_info->req->offset;
			compression = transfer_info->req->compression;
		}
		else {
			transfer_info->file = transfer_info->broadcast->file;
			size = transfer_info->broadcast->size;
			offset = transfer_info->broadcast->offset;
			compression = transfer_info->broadcast->compression;
		}

		/* Remaining data in this TCP connection is all file data.
		 * Always desegment if the size is 0 (ie. unknown)
		 */
		if (pinfo->can_desegment) {
			if (size == 0 || tvb_captured_length(tvb) < size) {
				pinfo->desegment_offset = 0;
				pinfo->desegment_len = DESEGMENT_UNTIL_FIN;
				return -1;
			}
		}

		/* OK. Now we have the whole file that was transferred. */
		transfer_info->resp_num = pinfo->num;
		transfer_info->resp_ts = pinfo->abs_ts;

		col_add_fstr(pinfo->cinfo, COL_INFO, "LDSS File Transfer (Sending file - %s)",
				     transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND
				     ? "pull"
				     : "push");

		ti = proto_tree_add_item(tree, proto_ldss,
				tvb, 0, tvb_reported_length(tvb), ENC_NA);
		ldss_tree = proto_item_add_subtree(ti, ett_ldss_transfer);
		proto_tree_add_bytes_format(ldss_tree, hf_ldss_file_data,
				tvb, 0, tvb_captured_length(tvb), NULL,
				compression == COMPRESSION_GZIP
				? "Gzip compressed data: %d bytes"
				: "File data: %d bytes",
				tvb_captured_length(tvb));
#ifdef HAVE_ZLIB
		/* Be nice and uncompress the file data. */
		if (compression == COMPRESSION_GZIP) {
			tvbuff_t *uncomp_tvb;
			uncomp_tvb = tvb_child_uncompress(tvb, tvb, 0, tvb_captured_length(tvb));
			if (uncomp_tvb != NULL) {
				/* XXX: Maybe not a good idea to add a data_source for
				   what may very well be a large buffer since then
				   the full uncompressed buffer will be shown in a tab
				   in the hex bytes pane ?
				   However, if we don't, bytes in an unrelated tab will
				   be highlighted.
				 */
				add_new_data_source(pinfo, uncomp_tvb, "Uncompressed Data");
				proto_tree_add_bytes_format_value(ldss_tree, hf_ldss_file_data,
						uncomp_tvb, 0, tvb_captured_length(uncomp_tvb),
						NULL, "Uncompressed data: %d bytes",
						tvb_captured_length(uncomp_tvb));
			}
		}
#endif
		ti = proto_tree_add_uint(ldss_tree, hf_ldss_digest_type,
				tvb, 0, 0, transfer_info->file->digest_type);
		PROTO_ITEM_SET_GENERATED(ti);
		if (transfer_info->file->digest != NULL) {
			/* This is ugly. You can't add bytes of nonzero length and have
			 * filtering work correctly unless you give a valid location in
			 * the packet. This hack pretends the first 32 bytes of the packet
			 * are the digest, which they aren't: they're actually the first 32
			 * bytes of the file that was sent. */
			ti = proto_tree_add_bytes(ldss_tree, hf_ldss_digest,
					tvb, 0, DIGEST_LEN, transfer_info->file->digest);
		}
		PROTO_ITEM_SET_GENERATED(ti);
		ti = proto_tree_add_uint64(ldss_tree, hf_ldss_size,
				tvb, 0, 0, size);
		PROTO_ITEM_SET_GENERATED(ti);
		ti = proto_tree_add_uint64(ldss_tree, hf_ldss_offset,
				tvb, 0, 0, offset);
		PROTO_ITEM_SET_GENERATED(ti);
		ti = proto_tree_add_uint(ldss_tree, hf_ldss_compression,
				tvb, 0, 0, compression);
		PROTO_ITEM_SET_GENERATED(ti);
		/* Link to the request for a pull. */
		if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND &&
				transfer_info->req != NULL &&
				transfer_info->req->num != 0) {
			ti = proto_tree_add_uint(ldss_tree, hf_ldss_response_to,
					tvb, 0, 0, transfer_info->req->num);
			PROTO_ITEM_SET_GENERATED(ti);
		}
	}

	/* Print the pull response time */
	if (transfer_info->broadcast->message_id == MESSAGE_ID_WILLSEND &&
	    transfer_info->req != NULL &&
	    transfer_info->resp_num != 0) {
		nstime_t pull_response_time;
		nstime_delta(&pull_response_time, &transfer_info->resp_ts,
			     &transfer_info->req->ts);
		ti = proto_tree_add_time(ldss_tree, hf_ldss_transfer_response_time,
					 tvb, 0, 0, &pull_response_time);
		PROTO_ITEM_SET_GENERATED(ti);
	}

	/* Link the transfer back to the initiating broadcast. Response time is
	 * calculated as the time from broadcast to completed transfer. */
	ti = proto_tree_add_uint(ldss_tree, hf_ldss_initiated_by,
				 tvb, 0, 0, transfer_info->broadcast->num);
	PROTO_ITEM_SET_GENERATED(ti);

	if (transfer_info->resp_num != 0) {
		nstime_delta(&broadcast_response_time, &transfer_info->resp_ts,
			     &transfer_info->broadcast->ts);
		ti = proto_tree_add_time(ldss_tree, hf_ldss_transfer_completed_in,
					 tvb, 0, 0, &broadcast_response_time);
		PROTO_ITEM_SET_GENERATED(ti);
	}

	/* This conv got its addr2/port2 set by the TCP dissector because a TCP
	 * connection was established. Make a new one to handle future connections
	 * to the addr/port mentioned in the broadcast, because that socket is
	 * still open. */
	if (transfer_tcpinfo->seq == 1 &&
	    transfer_tcpinfo->lastackseq == 1) {

		prepare_ldss_transfer_conv(transfer_info->broadcast);
	}

	return tvb_captured_length(tvb);
}
コード例 #2
0
ファイル: packet-adb.c プロジェクト: ARK1988/wireshark
static gint
dissect_adb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    proto_item      *main_item;
    proto_tree      *main_tree;
    proto_item      *arg0_item;
    proto_tree      *arg0_tree;
    proto_item      *arg1_item;
    proto_tree      *arg1_tree;
    proto_item      *magic_item;
    proto_item      *crc_item;
    proto_tree      *crc_tree = NULL;
    proto_item      *sub_item;
    gint             offset = 0;
    guint32          command;
    guint32          arg0;
    guint32          arg1;
    guint32          data_length = 0;
    guint32          crc32 = 0;
    usb_conv_info_t *usb_conv_info = NULL;
    wmem_tree_key_t  key[5];
    guint32          interface_id;
    guint32          bus_id;
    guint32          device_address;
    guint32          side_id;
    guint32          frame_number;
    gboolean         is_command = TRUE;
    gboolean         is_next_fragment = FALSE;
    gboolean         is_service = FALSE;
    gint             proto;
    gint             direction = P2P_DIR_UNKNOWN;
    wmem_tree_t     *wmem_tree;
    command_data_t  *command_data = NULL;
    service_data_t  *service_data = NULL;

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

    main_item = proto_tree_add_item(tree, proto_adb, tvb, offset, -1, ENC_NA);
    main_tree = proto_item_add_subtree(main_item, ett_adb);

    frame_number       = pinfo->fd->num;

    /* XXX: Why? If interface is USB only first try is correct
     * (and seems strange...), in other cases standard check for
     * previous protocol is correct */
    proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(/*wmem_list_frame_prev*/(wmem_list_tail(pinfo->layers))));
    if (proto != proto_usb) {
        proto = (gint) GPOINTER_TO_INT(wmem_list_frame_data(wmem_list_frame_prev(wmem_list_tail(pinfo->layers))));
    }

    if (proto == proto_usb) {
        usb_conv_info = (usb_conv_info_t *) data;
        DISSECTOR_ASSERT(usb_conv_info);

        direction = usb_conv_info->direction;
    } else if (proto == proto_tcp) {
        if (pinfo->destport == ADB_TCP_PORT)
            direction = P2P_DIR_SENT;
        else
            direction = P2P_DIR_RECV;
    } else {
        return offset;
    }

    if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
        interface_id = pinfo->phdr->interface_id;
    else
        interface_id = 0;

    if (proto == proto_usb) {
        bus_id             = usb_conv_info->bus_id;
        device_address     = usb_conv_info->device_address;

        key[0].length = 1;
        key[0].key = &interface_id;
        key[1].length = 1;
        key[1].key = &bus_id;
        key[2].length = 1;
        key[2].key = &device_address;
        key[3].length = 0;
        key[3].key = NULL;
    } else { /* tcp */
        key[0].length = 1;
        key[0].key = &interface_id;
        key[1].length = 1;
        key[2].length = 1;
        if (direction == P2P_DIR_SENT) {
            key[1].key = &pinfo->srcport;
            key[2].key = &pinfo->destport;
        } else {
            key[1].key = &pinfo->destport;
            key[2].key = &pinfo->srcport;
        }
        key[3].length = 0;
        key[3].key = NULL;
    }

    wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(command_info, key);
    if (wmem_tree) {
        command_data = (command_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
        if (command_data && command_data->completed_in_frame >= frame_number &&
                command_data->command_in_frame <= frame_number) {

            if (command_data->command_in_frame != frame_number) {
                is_command = FALSE;
                is_next_fragment = TRUE;
            }

            data_length = command_data->data_length;
            crc32 = command_data->crc32;

            if (direction == P2P_DIR_SENT)
                if (command_data->command == A_CLSE)
                    side_id = command_data->arg1; /* OUT: local id */
                else
                    side_id = command_data->arg0; /* OUT: local id */
            else
                if (command_data->command == A_OKAY) {
                    side_id = command_data->arg1; /* IN: remote id */
                } else
                    side_id = command_data->arg1; /* IN: remote id */

            key[3].length = 1;
            key[3].key = &side_id;
            key[4].length = 0;
            key[4].key = NULL;

            wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key);
            if (wmem_tree) {
                service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
                if (service_data && command_data->command == A_OPEN) {
                    is_service = TRUE;
                }
            }
        }
    }

/* Simple heuristics to check if packet is command or data */
    if ((command_data && command_data->completed_in_frame <= frame_number) || !command_data) {
        if (tvb_reported_length(tvb) < 24) {
            is_command = FALSE;
        } else if (tvb_reported_length(tvb) >= 24) {
            command = tvb_get_letohl(tvb, offset);

            if (command != A_SYNC && command != A_CLSE && command != A_WRTE &&
                    command != A_AUTH && command != A_CNXN && command != A_OPEN && command != A_OKAY)
                is_command = FALSE;
            else if (command != (0xFFFFFFFF ^ tvb_get_letohl(tvb, offset + 20)))
                is_command = FALSE;

            if (is_command) {
                data_length = tvb_get_letohl(tvb, offset + 12);
                crc32 = tvb_get_letohl(tvb, offset + 16);
            }
            if (command == A_OPEN) is_service = TRUE;
        }
    }

    if (service_data && !(command_data->command == A_OPEN && is_next_fragment)) {
        sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service_data->service);
        PROTO_ITEM_SET_GENERATED(sub_item);
    }

    if (service_data) {
        sub_item = proto_tree_add_uint(main_tree, hf_service_start_in_frame, tvb, offset, 0, service_data->start_in_frame);
        PROTO_ITEM_SET_GENERATED(sub_item);

        if (service_data->close_local_in_frame < max_in_frame) {
            sub_item = proto_tree_add_uint(main_tree, hf_close_local_in_frame, tvb, offset, 0, service_data->close_local_in_frame);
            PROTO_ITEM_SET_GENERATED(sub_item);
        }

        if (service_data->close_remote_in_frame < max_in_frame) {
            sub_item = proto_tree_add_uint(main_tree, hf_close_remote_in_frame, tvb, offset, 0, service_data->close_remote_in_frame);
            PROTO_ITEM_SET_GENERATED(sub_item);
        }
    }

    if (is_command) {
        proto_tree_add_item(main_tree, hf_command, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        command = tvb_get_letohl(tvb, offset);
        offset += 4;

        col_append_str(pinfo->cinfo, COL_INFO, val_to_str_const(command, command_vals, "Unknown command"));

        arg0_item = proto_tree_add_item(main_tree, hf_argument_0, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        arg0_tree = proto_item_add_subtree(arg0_item, ett_adb_arg0);
        arg0 = tvb_get_letohl(tvb, offset);
        offset += 4;

        arg1_item = proto_tree_add_item(main_tree, hf_argument_1, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        arg1_tree = proto_item_add_subtree(arg1_item, ett_adb_arg1);
        arg1 = tvb_get_letohl(tvb, offset);
        offset += 4;

        switch (command) {
        case A_CNXN:
            proto_tree_add_item(arg0_tree, hf_version, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_max_data, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(version=%u.%u.%u, max_data=%u)", tvb_get_guint8(tvb, offset - 5), tvb_get_guint8(tvb, offset - 6), tvb_get_letohs(tvb, offset - 7), tvb_get_letohl(tvb, offset - 4));
            break;
        case A_AUTH:
            proto_tree_add_item(arg0_tree, hf_auth_type, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(type=%s, 0)", val_to_str_const(tvb_get_letohl(tvb, offset - 8), auth_type_vals, "Unknown"));
            break;
        case A_OPEN:
            proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_zero, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, 0)", tvb_get_letohl(tvb, offset - 8));
            break;
        case A_WRTE:
            proto_tree_add_item(arg0_tree, hf_zero, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(0, remote=%u)", tvb_get_letohl(tvb, offset - 4));
            break;
        case A_CLSE:
        case A_OKAY:
            proto_tree_add_item(arg0_tree, hf_local_id, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_remote_id, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(local=%u, remote=%u)", tvb_get_letohl(tvb, offset - 8), tvb_get_letohl(tvb, offset - 4));
            break;
        case A_SYNC:
            proto_tree_add_item(arg0_tree, hf_online, tvb, offset - 8, 4, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(arg1_tree, hf_sequence, tvb, offset - 4, 4, ENC_LITTLE_ENDIAN);

            col_append_fstr(pinfo->cinfo, COL_INFO, "(online=%s, sequence=%u)", tvb_get_letohl(tvb, offset - 8) ? "Yes": "No", tvb_get_letohl(tvb, offset - 4));
            break;
        }

        proto_tree_add_item(main_tree, hf_data_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        offset += 4;

        if (data_length > 0)
            col_append_fstr(pinfo->cinfo, COL_INFO, " length=%u ", data_length);

        crc_item = proto_tree_add_item(main_tree, hf_data_crc32, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc);
        crc32 = tvb_get_letohl(tvb, offset);
        offset += 4;

        magic_item = proto_tree_add_item(main_tree, hf_magic, tvb, offset, 4, ENC_LITTLE_ENDIAN);
        if ((tvb_get_letohl(tvb, offset) ^ 0xFFFFFFFF) != command) {
            proto_tree  *expert_tree;

            expert_tree = proto_item_add_subtree(magic_item, ett_adb_magic);
            proto_tree_add_expert(expert_tree, pinfo, &ei_invalid_magic, tvb, offset, 4);
        }

        if (!pinfo->fd->flags.visited)
            save_command(command, arg0, arg1, data_length, crc32, service_data, proto, data, pinfo, &service_data, &command_data);
        offset += 4;
    }

    if (!pinfo->fd->flags.visited && command_data) {
            if (command_data->command_in_frame != frame_number) {
                is_command = FALSE;
                is_next_fragment = TRUE;
            }

            data_length = command_data->data_length;
            crc32 = command_data->crc32;

            if ((command_data->command_in_frame != frame_number && tvb_captured_length(tvb) == data_length) ||
                (command_data->command_in_frame == frame_number && tvb_captured_length(tvb) == data_length + 24)
            ) {
                command_data->reassemble_data_length = command_data->data_length;
                command_data->completed_in_frame = frame_number;
            }
    }

    if (is_next_fragment && command_data) {
        sub_item = proto_tree_add_uint(main_tree, hf_command_in_frame, tvb, offset, 0, command_data->command_in_frame);
        PROTO_ITEM_SET_GENERATED(sub_item);

        sub_item = proto_tree_add_uint(main_tree, hf_command, tvb, offset, 0, command_data->command);
        PROTO_ITEM_SET_GENERATED(sub_item);

        sub_item = proto_tree_add_uint(main_tree, hf_data_length, tvb, offset, 0, command_data->data_length);
        PROTO_ITEM_SET_GENERATED(sub_item);

        crc_item = proto_tree_add_uint(main_tree, hf_data_crc32, tvb, offset, 0, command_data->crc32);
        crc_tree = proto_item_add_subtree(crc_item, ett_adb_crc);
        PROTO_ITEM_SET_GENERATED(crc_item);
    }

    if (command_data && command_data->completed_in_frame != frame_number) {
        sub_item = proto_tree_add_uint(main_tree, hf_completed_in_frame, tvb, offset, 0, command_data->completed_in_frame);
        PROTO_ITEM_SET_GENERATED(sub_item);
    }


    if (tvb_captured_length_remaining(tvb, offset) > 0 && (!is_command || data_length > 0)) {
        guint32 crc = 0;
        guint32 i_offset;

        if ((!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) || data_length > (guint32) tvb_captured_length_remaining(tvb, offset)) { /* need reassemble */
            if (!pinfo->fd->flags.visited && command_data && command_data->reassemble_data_length < command_data->data_length) {
                tvb_memcpy(tvb, command_data->reassemble_data + command_data->reassemble_data_length, offset, tvb_captured_length_remaining(tvb, offset));
                command_data->reassemble_data_length += tvb_captured_length_remaining(tvb, offset);

                if (command_data->reassemble_data_length >= command_data->data_length)
                    command_data->completed_in_frame = frame_number;
            }

            proto_tree_add_item(main_tree, hf_data_fragment, tvb, offset, -1, ENC_NA);
            col_append_str(pinfo->cinfo, COL_INFO, "Data Fragment");
            offset = tvb_captured_length(tvb);

            if (service_data && command_data && command_data->reassemble_data_length >= command_data->data_length && frame_number == command_data->completed_in_frame) {
                tvbuff_t            *next_tvb;
                adb_service_data_t   adb_service_data;

                next_tvb = tvb_new_child_real_data(tvb, command_data->reassemble_data, command_data->reassemble_data_length, command_data->reassemble_data_length);
                add_new_data_source(pinfo, next_tvb, "ADB Reassembled Data");

                adb_service_data.service = service_data->service;
                adb_service_data.direction = direction;

                adb_service_data.session_key_length = 3;
                adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32));
                adb_service_data.session_key[0] = interface_id;

                if (proto == proto_usb) {
                    adb_service_data.session_key[1] = usb_conv_info->bus_id;
                    adb_service_data.session_key[2] = usb_conv_info->device_address;
                } else { /* tcp */
                    if (direction == P2P_DIR_SENT) {
                        adb_service_data.session_key[1] = pinfo->srcport;
                        adb_service_data.session_key[2] = pinfo->destport;
                    } else {
                        adb_service_data.session_key[1] = pinfo->destport;
                        adb_service_data.session_key[2] = pinfo->srcport;
                    }
                }

                call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data);
            }
        } else { /* full message */
            for (i_offset = 0; i_offset < data_length; ++i_offset)
                crc += tvb_get_guint8(tvb, offset + i_offset);

            if (crc32 > 0 && crc32 != crc)
                proto_tree_add_expert(crc_tree, pinfo, &ei_invalid_crc, tvb, offset, -1);

            if (is_service) {
                proto_tree_add_item(main_tree, hf_service, tvb, offset, -1, ENC_ASCII | ENC_NA);
                if (!pinfo->fd->flags.visited && service_data) {
                    service_data->service = tvb_get_stringz_enc(wmem_file_scope(), tvb, offset, NULL, ENC_ASCII);
                }
                col_append_fstr(pinfo->cinfo, COL_INFO, "Service: %s", tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, NULL, ENC_ASCII));
                offset = tvb_captured_length(tvb);
            } else if (command_data && command_data->command == A_CNXN) {
                    gchar       *info;
                    gint         len;

                info = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &len, ENC_ASCII);
                col_append_fstr(pinfo->cinfo, COL_INFO, "Connection Info: %s", info);
                proto_tree_add_item(main_tree, hf_connection_info, tvb, offset, len, ENC_ASCII | ENC_NA);
                offset += len;
            } else {
                col_append_str(pinfo->cinfo, COL_INFO, "Data");

                /* Decode service payload */
                if (service_data) {
                    tvbuff_t           *next_tvb;
                    adb_service_data_t  adb_service_data;

                    adb_service_data.service = service_data->service;
                    adb_service_data.direction = direction;

                    adb_service_data.session_key_length = 3;
                    adb_service_data.session_key = (guint32 *) wmem_alloc(wmem_packet_scope(), adb_service_data.session_key_length * sizeof(guint32));
                    adb_service_data.session_key[0] = interface_id;

                    if (proto == proto_usb) {
                        adb_service_data.session_key[1] = usb_conv_info->bus_id;
                        adb_service_data.session_key[2] = usb_conv_info->device_address;
                    } else { /* tcp */
                        if (direction == P2P_DIR_SENT) {
                            adb_service_data.session_key[1] = pinfo->srcport;
                            adb_service_data.session_key[2] = pinfo->destport;
                        } else {
                            adb_service_data.session_key[1] = pinfo->destport;
                            adb_service_data.session_key[2] = pinfo->srcport;
                        }
                    }

                    next_tvb = tvb_new_subset(tvb, offset, tvb_captured_length_remaining(tvb, offset), tvb_captured_length_remaining(tvb, offset));
                    call_dissector_with_data(adb_service_handle, next_tvb, pinfo, tree, &adb_service_data);

                } else {
                    proto_item  *data_item;
                    gchar       *data_str;

                    data_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, data_length, ENC_NA);
                    data_str = tvb_format_text(tvb, offset, data_length);
                    proto_item_append_text(data_item, ": %s", data_str);
                    col_append_fstr(pinfo->cinfo, COL_INFO, " Raw: %s", data_str);
                }

                offset = tvb_captured_length(tvb);
            }
        }
    }

    return offset;
}
コード例 #3
0
ファイル: packet-socks.c プロジェクト: pvons/wireshark
static void
socks_udp_dissector(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {

/* Conversation dissector called from UDP dissector. Decode and display */
/* the socks header, the pass the rest of the data to the udp port  */
/* decode routine to  handle the payload.               */

    int                 offset = 0;
    guint32            *ptr;
    socks_hash_entry_t *hash_info;
    conversation_t     *conversation;
    proto_tree         *socks_tree;
    proto_item         *ti;

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

    DISSECTOR_ASSERT( conversation);    /* should always find a conversation */

    hash_info = (socks_hash_entry_t *)conversation_get_proto_data(conversation, proto_socks);

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Socks");
    col_set_str(pinfo->cinfo, COL_INFO, "Version: 5, UDP Associated packet");

    if ( tree) {
        ti = proto_tree_add_protocol_format( tree, proto_socks, tvb, offset, -1, "Socks" );

        socks_tree = proto_item_add_subtree(ti, ett_socks);

        proto_tree_add_item(socks_tree, hf_socks_reserved2, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;

        proto_tree_add_item(socks_tree, hf_socks_fragment_number, tvb, offset, 1, ENC_NA);
        offset += 1;

        offset = display_address( tvb, offset, socks_tree);
        hash_info->udp_remote_port = tvb_get_ntohs(tvb, offset);

        proto_tree_add_uint( socks_tree, hf_socks_dstport, tvb,
            offset, 2, hash_info->udp_remote_port);

        offset += 2;
    }
    else {      /* no tree, skip past the socks header */
        offset += 3;
        offset = get_address_v5( tvb, offset, 0) + 2;
    }

    /* set pi src/dst port and call the udp sub-dissector lookup */

    if ( pinfo->srcport == hash_info->port)
        ptr = &pinfo->destport;
    else
        ptr = &pinfo->srcport;

    *ptr = hash_info->udp_remote_port;

    decode_udp_ports( tvb, offset, pinfo, tree, pinfo->srcport, pinfo->destport, -1);

    *ptr = hash_info->udp_port;
}
コード例 #4
0
static void
gbl_symbols_new(void) {
  DISSECTOR_ASSERT(gbl_symbols_array == NULL);
  gbl_symbols_array = g_array_new(TRUE, TRUE, sizeof(value_string));
}
コード例 #5
0
/* Both Source-Active and Source-Active Response have the same format
 * with one exception. Encapsulated multicast data is not allowed in
 * SA Response.
 */
static void dissect_msdp_sa(tvbuff_t *tvb, packet_info *pinfo,
    proto_tree *tree, int *offset, int length)
{
        guint8 entries;

        if (length < 1)
                return;
        entries = tvb_get_guint8(tvb, *offset);
        proto_tree_add_uint(tree, hf_msdp_sa_entry_count, tvb, *offset, 1, entries);
        *offset += 1;
        length -= 1;

        if (length < 4) {
                *offset += length;
                return;
        }
        proto_tree_add_item(tree, hf_msdp_sa_rp_addr, tvb, *offset, 4, ENC_BIG_ENDIAN);
        *offset += 4;
        length -= 4;

        /* Put each of the (S,G) entries in their own subtree.
         * This is probably visually better.
         */
        while (entries-- > 0) {
                proto_item *ei;
                proto_tree *entry_tree;

                if (length < 12) {
                        *offset += length;
                        return;
                }
                ei = proto_tree_add_text(tree, tvb, *offset, 12, "(S,G) block: %s/%u -> %s",
                                         tvb_ip_to_str(tvb, *offset + 8),
                                         tvb_get_guint8(tvb, *offset + 3),
                                         tvb_ip_to_str(tvb, *offset + 4));
                entry_tree = proto_item_add_subtree(ei, ett_msdp_sa_entry);

                proto_tree_add_item(entry_tree, hf_msdp_sa_reserved, tvb, *offset, 3, ENC_BIG_ENDIAN);
                *offset += 3;
                length -= 3;
                proto_tree_add_item(entry_tree, hf_msdp_sa_sprefix_len, tvb, *offset, 1, ENC_BIG_ENDIAN);
                *offset += 1;
                length -= 1;
                proto_tree_add_item(entry_tree, hf_msdp_sa_group_addr, tvb, *offset, 4, ENC_BIG_ENDIAN);
                *offset += 4;
                length -= 4;
                proto_tree_add_item(entry_tree, hf_msdp_sa_src_addr, tvb, *offset, 4, ENC_BIG_ENDIAN);
                *offset += 4;
                length -= 4;
        }

        /*
         * Check if an encapsulated multicast IPv4 packet follows
         */
        if (length > 0) {
                proto_item *ei;
                proto_tree *enc_tree;
                gint available_length, reported_length;
                tvbuff_t *next_tvb;

                ei = proto_tree_add_text(tree, tvb, *offset, length,
                                         "Encapsulated IPv4 packet: %u bytes",
                                         length);
                enc_tree = proto_item_add_subtree(ei, ett_msdp_sa_enc_data);

                available_length = tvb_length_remaining(tvb, *offset);
                reported_length = tvb_reported_length_remaining(tvb, *offset);
                DISSECTOR_ASSERT(available_length >= 0);
                DISSECTOR_ASSERT(reported_length >= 0);
                if (available_length > reported_length)
                        available_length = reported_length;
                if (available_length > length)
                        available_length = length;
                if (reported_length > length)
                        reported_length = length;

                next_tvb = tvb_new_subset(tvb, *offset, available_length,
                                          reported_length);
                /* Set the information columns read-only so that they
                 * reflect the MSDP packet rather than the
                 * encapsulated packet.
                 */
                col_set_writable(pinfo->cinfo, FALSE);
                call_dissector(ip_handle, next_tvb, pinfo, enc_tree);
        }
        *offset += length;

        return;
}
コード例 #6
0
ファイル: stream.c プロジェクト: acaceres2176/wireshark
fragment_head *stream_get_frag_data( const stream_pdu_fragment_t *frag)
{
    DISSECTOR_ASSERT( frag );
    return frag->pdu->fd_head;
}
コード例 #7
0
ファイル: packet-xmpp.c プロジェクト: drower/wireshark-1.10.0
static void
dissect_xmpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {

    xml_frame_t *xml_frame;
    gboolean     out_packet;

    conversation_t   *conversation;
    xmpp_conv_info_t *xmpp_info;

    proto_tree *xmpp_tree  = NULL;
    proto_item *xmpp_item  = NULL;

    xmpp_element_t *packet = NULL;

    /*check if desegment
     * now it checks that last char is '>',
     * TODO checks that first element in packet is closed*/
    int   indx;
    gchar last_char;

    if (xmpp_desegment)
    {
        indx = tvb_reported_length(tvb) - 1;
        if (indx >= 0)
        {
            last_char = tvb_get_guint8(tvb, indx);

            while ((last_char <= ' ') && (indx - 1 >= 0))
            {
                indx--;
                last_char = tvb_get_guint8(tvb, indx);
            }

            if ((indx >= 0) && (last_char != '>'))
            {
                pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
                return;
            }
        }
    }

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

    col_clear(pinfo->cinfo, COL_INFO);

    conversation = find_or_create_conversation(pinfo);
    xmpp_info = (xmpp_conv_info_t *)conversation_get_proto_data(conversation, proto_xmpp);

    if (xmpp_info && xmpp_info->ssl_proceed &&
            xmpp_info->ssl_proceed < pinfo->fd->num)
    {
        call_dissector(ssl_handle, tvb, pinfo, tree);
        return;
    }

    /*if tree == NULL then xmpp_item and xmpp_tree will also NULL*/
    xmpp_item = proto_tree_add_item(tree, proto_xmpp, tvb, 0, -1, ENC_NA);
    xmpp_tree = proto_item_add_subtree(xmpp_item, ett_xmpp);

    call_dissector(xml_handle, tvb, pinfo, xmpp_tree);

    /* If XML dissector is disabled, we can't do much */
    if (!proto_is_protocol_enabled(find_protocol_by_id(dissector_handle_get_protocol_index(xml_handle))))
    {
        col_append_str(pinfo->cinfo, COL_INFO, "(XML dissector disabled, can't dissect XMPP)");
        expert_add_info_format(pinfo, xmpp_item, PI_UNDECODED, PI_WARN, "XML dissector disabled, can't dissect XMPP");
        return;
    }

    /*if stream end occurs then return*/
    if(xmpp_stream_close(xmpp_tree,tvb, pinfo))
    {
        if(xmpp_tree)
            xmpp_proto_tree_hide_first_child(xmpp_tree);
        return;
    }

    if(!pinfo->private_data)
        return;

    /*data from XML dissector*/
    xml_frame = ((xml_frame_t*)pinfo->private_data)->first_child;

    if(!xml_frame)
        return;

    if (!xmpp_info) {
        xmpp_info = se_new(xmpp_conv_info_t);
        xmpp_info->req_resp = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_req_resp");
        xmpp_info->jingle_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_jingle_sessions");
        xmpp_info->ibb_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_ibb_sessions");
        xmpp_info->gtalk_sessions = se_tree_create_non_persistent(EMEM_TREE_TYPE_RED_BLACK, "xmpp_gtalk_sessions");
        xmpp_info->ssl_start   = 0;
        xmpp_info->ssl_proceed = 0;
        conversation_add_proto_data(conversation, proto_xmpp, (void *) xmpp_info);
    }

    if (pinfo->match_uint == pinfo->destport)
        out_packet = TRUE;
    else
        out_packet = FALSE;

    while(xml_frame)
    {
        packet = xmpp_xml_frame_to_element_t(xml_frame, NULL, tvb);
        DISSECTOR_ASSERT(packet);

        if (strcmp(packet->name, "iq") == 0) {
            xmpp_iq_reqresp_track(pinfo, packet, xmpp_info);
            xmpp_jingle_session_track(pinfo, packet, xmpp_info);
            xmpp_gtalk_session_track(pinfo, packet, xmpp_info);
        }

        if (strcmp(packet->name, "iq") == 0 || strcmp(packet->name, "message") == 0) {
            xmpp_ibb_session_track(pinfo, packet, xmpp_info);
        }

        if (tree) { /* we are being asked for details */
            proto_item *outin_item;

            if (out_packet)
                outin_item = proto_tree_add_boolean(xmpp_tree, hf_xmpp_out, tvb, 0, 0, TRUE);
            else
                outin_item = proto_tree_add_boolean(xmpp_tree, hf_xmpp_in, tvb, 0, 0, TRUE);

            PROTO_ITEM_SET_HIDDEN(outin_item);


            /*it hides tree generated by XML dissector*/
            xmpp_proto_tree_hide_first_child(xmpp_tree);

            if (strcmp(packet->name, "iq") == 0) {
                xmpp_iq(xmpp_tree, tvb, pinfo, packet);
            } else if (strcmp(packet->name, "presence") == 0) {
                xmpp_presence(xmpp_tree, tvb, pinfo, packet);
            } else if (strcmp(packet->name, "message") == 0) {
                xmpp_message(xmpp_tree, tvb, pinfo, packet);
            } else if (strcmp(packet->name, "auth") == 0) {
                xmpp_auth(xmpp_tree, tvb, pinfo, packet);
            } else if (strcmp(packet->name, "challenge") == 0) {
                xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_challenge, ett_xmpp_challenge, "CHALLENGE");
            } else if (strcmp(packet->name, "response") == 0) {
                xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_response, ett_xmpp_response, "RESPONSE");
            } else if (strcmp(packet->name, "success") == 0) {
                xmpp_challenge_response_success(xmpp_tree, tvb, pinfo, packet, hf_xmpp_success, ett_xmpp_success, "SUCCESS");
            } else if (strcmp(packet->name, "failure") == 0) {
                xmpp_failure(xmpp_tree, tvb, pinfo, packet);
            } else if (strcmp(packet->name, "xml") == 0) {
                xmpp_xml_header(xmpp_tree, tvb, pinfo, packet);
            } else if (strcmp(packet->name, "stream") == 0) {
                xmpp_stream(xmpp_tree, tvb, pinfo, packet);
            } else if (strcmp(packet->name, "features") == 0) {
                xmpp_features(xmpp_tree, tvb, pinfo, packet);
            } else if (strcmp(packet->name, "starttls") == 0) {
                xmpp_starttls(xmpp_tree, tvb, pinfo, packet, xmpp_info);
            }else if (strcmp(packet->name, "proceed") == 0) {
                xmpp_proceed(xmpp_tree, tvb, pinfo, packet, xmpp_info);
            }else {
                xmpp_proto_tree_show_first_child(xmpp_tree);
                expert_add_info_format(pinfo, xmpp_tree, PI_UNDECODED, PI_NOTE, "Unknown packet: %s", packet->name);
                col_clear(pinfo->cinfo, COL_INFO);
                col_append_fstr(pinfo->cinfo, COL_INFO, "UNKNOWN PACKET ");
            }

            /*appends to COL_INFO information about src or dst*/
            if (pinfo->match_uint == pinfo->destport) {
                xmpp_attr_t *to = xmpp_get_attr(packet, "to");
                if (to)
                    col_append_fstr(pinfo->cinfo, COL_INFO, "> %s ", to->value);
            } else {
                xmpp_attr_t *from = xmpp_get_attr(packet, "from");
                if (from)
                    col_append_fstr(pinfo->cinfo, COL_INFO, "< %s ", from->value);
            }
        }

        xmpp_element_t_tree_free(packet);
        xml_frame = xml_frame->next_sibling;
    }
}
コード例 #8
0
ファイル: asn1.c プロジェクト: nehaahir/wireshark
void asn1_stack_frame_pop(asn1_ctx_t *actx, const gchar *name) {
  DISSECTOR_ASSERT(actx->stack);
  DISSECTOR_ASSERT(!strcmp(actx->stack->name, name));
  actx->stack = actx->stack->next;
}
コード例 #9
0
ファイル: gcp.c プロジェクト: koyeen/wireshark
gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean keep_persistent_data) {
    gcp_trx_t* t = NULL;
    gcp_trx_msg_t* trxmsg;

    if ( !m ) return NULL;

    if (keep_persistent_data) {
        if (m->committed) {

            for ( trxmsg = m->trxs; trxmsg; trxmsg = trxmsg->next) {
                if (trxmsg->trx && trxmsg->trx->id == t_id) {
                    return trxmsg->trx;
                }
            }
            DISSECTOR_ASSERT_NOT_REACHED();
        } else {
            wmem_tree_key_t key[4];

            key[0].length = 1;
            key[0].key = &(m->hi_addr);
            key[1].length = 1;
            key[1].key = &(m->lo_addr);
            key[2].length = 1;
            key[2].key = &(t_id);
            key[3].length = 0;
            key[3].key = NULL;

            trxmsg = wmem_new(wmem_file_scope(), gcp_trx_msg_t);
            t = (gcp_trx_t *)wmem_tree_lookup32_array(trxs,key);

            if (!t) {
                t = wmem_new(wmem_file_scope(), gcp_trx_t);
                t->initial = m;
                t->id = t_id;
                t->type = type;
                t->pendings = 0;
                t->error = 0;
                t->cmds = NULL;

                wmem_tree_insert32_array(trxs,key,t);
            }

            /* XXX: request, reply and ack + point to frames where they are */
            switch ( type ) {
                case GCP_TRX_PENDING:
                    t->pendings++;
                    break;
                default:
                    break;
            }

        }
    } else {
        t = wmem_new(wmem_packet_scope(), gcp_trx_t);
        trxmsg = wmem_new(wmem_packet_scope(), gcp_trx_msg_t);
        t->initial = NULL;
        t->id = t_id;
        t->type = type;
        t->pendings = 0;
        t->error = 0;
        t->cmds = NULL;
    }

    DISSECTOR_ASSERT(trxmsg);

    trxmsg->trx = t;
    trxmsg->next = NULL;
    trxmsg->last = trxmsg;

    if (m->trxs) {
        m->trxs->last = m->trxs->last->next = trxmsg;
    } else {
        m->trxs = trxmsg;
    }

    return t;
}
コード例 #10
0
gcp_cmd_t* gcp_cmd(gcp_msg_t* m, gcp_trx_t* t, gcp_ctx_t* c, gcp_cmd_type_t type, guint offset, gboolean persistent) {
    gcp_cmd_t* cmd;
    gcp_cmd_msg_t* cmdtrx;
    gcp_cmd_msg_t* cmdctx;

    if ( !m || !t || !c ) return NULL;

    if (persistent) {
        if (m->commited) {
            DISSECTOR_ASSERT(t->cmds != NULL);

            for (cmdctx = t->cmds; cmdctx; cmdctx = cmdctx->next) {
                cmd = cmdctx->cmd;
                if (cmd->msg == m && cmd->offset == offset) {
                    return cmd;
                }
            }

            DISSECTOR_ASSERT(!"called for a command that does not exist!");

            return NULL;
        } else {
            cmd = se_alloc(sizeof(gcp_cmd_t));
            cmdtrx = se_alloc(sizeof(gcp_cmd_msg_t));
            cmdctx = se_alloc(sizeof(gcp_cmd_msg_t));
        }
    } else {
        cmd = ep_new(gcp_cmd_t);
        cmdtrx = ep_new(gcp_cmd_msg_t);
        cmdctx = ep_new(gcp_cmd_msg_t);
    }

    cmd->type = type;
    cmd->offset = offset;
    cmd->terms.term = NULL;
    cmd->terms.next = NULL;
    cmd->terms.last = &(cmd->terms);
    cmd->str = NULL;
    cmd->msg = m;
    cmd->trx = t;
    cmd->ctx = c;
    cmd->error = 0;

    cmdctx->cmd = cmdtrx->cmd = cmd;
    cmdctx->next =  cmdtrx->next = NULL;
    cmdctx->last = cmdtrx->last = NULL;

    if (t->cmds) {
        t->cmds->last->next = cmdtrx;
        t->cmds->last = cmdtrx;
    } else {
        t->cmds = cmdtrx;
        t->cmds->last = cmdtrx;
    }

    if (c->cmds) {
        c->cmds->last->next = cmdctx;
        c->cmds->last = cmdctx;
    } else {
        c->cmds = cmdctx;
        c->cmds->last = cmdctx;
    }

    return cmd;
}
コード例 #11
0
ファイル: value_string.c プロジェクト: qnofae/wireshark
/* Initializes an extended value string. Behaves like a match function to
 * permit lazy initialization of extended value strings.
 * - Goes through the value_string array to determine the fastest possible
 *   access method.
 * - Verifies that the value_string contains no NULL string pointers.
 * - Verifies that the value_string is terminated by {0, NULL}
 */
const value_string *
_try_val_to_str_ext_init(const guint32 val, const value_string_ext *a_vse)
{
    /* Cast away the constness!
     * It's better if the prototype for this function matches the other
     * _try_val_to_str_* functions (so we don't have to cast it when storing it
     * in _try_val_to_str so the compiler will notice if the prototypes get out
     * of sync), but the init function is unique in that it does actually
     * modify the vse.
     */
    value_string_ext    *vse            = (value_string_ext *)a_vse;

    const value_string *vs_p           = vse->_vs_p;
    const guint         vs_num_entries = vse->_vs_num_entries;

    /* The matching algorithm used:
     * VS_SEARCH   - slow sequential search (as in a normal value string)
     * VS_BIN_TREE - log(n)-time binary search, the values must be sorted
     * VS_INDEX    - constant-time index lookup, the values must be contiguous
     */
    enum { VS_SEARCH, VS_BIN_TREE, VS_INDEX } type = VS_INDEX;

    /* Note: The value_string 'value' is *unsigned*, but we do a little magic
     * to help with value strings that have negative values.
     *
     * { -3, -2, -1, 0, 1, 2 }
     * will be treated as "ascending ordered" (although it isn't technically),
     * thus allowing constant-time index search
     *
     * { -3, -2, 0, 1, 2 } and { -3, -2, -1, 0, 2 }
     * will both be considered as "out-of-order with gaps", thus falling
     * back to the slow linear search
     *
     * { 0, 1, 2, -3, -2 } and { 0, 2, -3, -2, -1 }
     * will be considered "ascending ordered with gaps" thus allowing
     * a log(n)-time 'binary' search
     *
     * If you're confused, think of how negative values are represented, or
     * google two's complement.
     */

    guint32 prev_value;
    guint   first_value;
    guint   i;

    DISSECTOR_ASSERT((vs_p[vs_num_entries].value  == 0) &&
                     (vs_p[vs_num_entries].strptr == NULL));

    vse->_vs_first_value = vs_p[0].value;
    first_value          = vs_p[0].value;
    prev_value           = first_value;

    for (i = 0; i < vs_num_entries; i++) {
        DISSECTOR_ASSERT(vs_p[i].strptr != NULL);
        if ((type == VS_INDEX) && (vs_p[i].value != (i + first_value))) {
            type = VS_BIN_TREE;
        }
        /* XXX: Should check for dups ?? */
        if (type == VS_BIN_TREE) {
            if (prev_value > vs_p[i].value) {
                g_warning("Extended value string %s forced to fall back to linear search: entry %u, value %u < previous entry, value %u",
                        vse->_vs_name, i, vs_p[i].value, prev_value);
                type = VS_SEARCH;
                break;
            }
            if (first_value > vs_p[i].value) {
                g_warning("Extended value string %s forced to fall back to linear search: entry %u, value %u < first entry, value %u",
                        vse->_vs_name, i, vs_p[i].value, first_value);
                type = VS_SEARCH;
                break;
            }
        }

        prev_value = vs_p[i].value;
    }

    switch (type) {
        case VS_SEARCH:
            vse->_vs_match2 = _try_val_to_str_linear;
            break;
        case VS_BIN_TREE:
            vse->_vs_match2 = _try_val_to_str_bsearch;
            break;
        case VS_INDEX:
            vse->_vs_match2 = _try_val_to_str_index;
            break;
        default:
            g_assert_not_reached();
            break;
    }

    return vse->_vs_match2(val, vse);
}
コード例 #12
0
gcp_ctx_t* gcp_ctx(gcp_msg_t* m, gcp_trx_t* t, guint32 c_id, gboolean persistent) {
    gcp_ctx_t* context = NULL;
    gcp_ctx_t** context_p = NULL;

    if ( !m || !t ) return NULL;

    if (persistent) {

        emem_tree_key_t ctx_key[] = {
            {1,&(m->hi_addr)},
            {1,&(m->lo_addr)},
            {1,&(c_id)},
            {0,NULL}
        };

        emem_tree_key_t trx_key[] = {
            {1,&(m->hi_addr)},
            {1,&(m->lo_addr)},
            {1,&(t->id)},
            {0,NULL}
        };

        if (m->commited) {
            if (( context = se_tree_lookup32_array(ctxs_by_trx,trx_key) )) {
                return context;
            } if ((context_p = se_tree_lookup32_array(ctxs,ctx_key))) {
                context = *context_p;

                do {
                    if (context->initial->framenum <= m->framenum) {
                        return context;
                    }
                } while(( context = context->prev ));

                DISSECTOR_ASSERT(! "a context should exist");
            }
        } else {
            if (c_id == CHOOSE_CONTEXT) {
                if (! ( context = se_tree_lookup32_array(ctxs_by_trx,trx_key))) {
                    context = se_alloc(sizeof(gcp_ctx_t));
                    context->initial = m;
                    context->cmds = NULL;
                    context->id = c_id;
                    context->terms.last = &(context->terms);
                    context->terms.next = NULL;
                    context->terms.term = NULL;

                    se_tree_insert32_array(ctxs_by_trx,trx_key,context);
                }
            } else {
                if (( context = se_tree_lookup32_array(ctxs_by_trx,trx_key) )) {
                    if (( context_p = se_tree_lookup32_array(ctxs,ctx_key) )) {
                        if (context != *context_p) {
                            if(context->id != CHOOSE_CONTEXT) {
                                context = se_alloc(sizeof(gcp_ctx_t));
                            }
                            context->initial = m;
                            context->id = c_id;
                            context->cmds = NULL;
                            context->terms.last = &(context->terms);
                            context->terms.next = NULL;
                            context->terms.term = NULL;

                            context->prev = *context_p;
                            *context_p = context;
                        }
                    } else {
                        context_p = se_alloc(sizeof(void*));
                        *context_p = context;
                        context->initial = m;
                        context->id = c_id;
                        se_tree_insert32_array(ctxs,ctx_key,context_p);
                    }
                } else if (! ( context_p = se_tree_lookup32_array(ctxs,ctx_key) )) {
                    context = se_alloc(sizeof(gcp_ctx_t));
                    context->initial = m;
                    context->id = c_id;
                    context->cmds = NULL;
                    context->terms.last = &(context->terms);
                    context->terms.next = NULL;
                    context->terms.term = NULL;

                    context_p = se_alloc(sizeof(void*));
                    *context_p = context;
                    se_tree_insert32_array(ctxs,ctx_key,context_p);
                } else {
                    context = *context_p;
                }
            }
        }
    } else {
        context = ep_new(gcp_ctx_t);
        context->initial = m;
        context->cmds = NULL;
        context->id = c_id;
        context->terms.last = &(context->terms);
        context->terms.next = NULL;
        context->terms.term = NULL;
    }

    return context;
}
コード例 #13
0
ファイル: rawshark.c プロジェクト: RazZziel/wireshark-dplay
static gboolean print_field_value(field_info *finfo, int cmd_line_index)
{
	header_field_info	*hfinfo;
	static char			*fs_buf = NULL;
	char				*fs_ptr = fs_buf;
	static GString     *label_s = NULL;
	int					fs_buf_len = FIELD_STR_INIT_LEN, fs_len;
	guint              i;
	string_fmt_t       *sf;
	guint32            uvalue;
	gint32             svalue;
	const true_false_string *tfstring = &tfs_true_false;

	hfinfo = finfo->hfinfo;

	if (!fs_buf) {
		fs_buf = g_malloc(fs_buf_len + 1);
		fs_ptr = fs_buf;
	}

	if (!label_s) {
		label_s = g_string_new("");
	}

	if(finfo->value.ftype->val_to_string_repr)
	{
		/*
		 * this field has an associated value,
		 * e.g: ip.hdr_len
		 */
		fs_len = fvalue_string_repr_len(&finfo->value, FTREPR_DFILTER);
		while (fs_buf_len < fs_len) {
			fs_buf_len *= 2;
			fs_buf = g_realloc(fs_buf, fs_buf_len + 1);
			fs_ptr = fs_buf;
		}
		fvalue_to_string_repr(&finfo->value,
			FTREPR_DFILTER,
			fs_buf);

		/* String types are quoted. Remove them. */
		if ((finfo->value.ftype->ftype == FT_STRING || finfo->value.ftype->ftype == FT_STRINGZ) && fs_len > 2) {
			fs_buf[fs_len - 1] = '\0';
			fs_ptr++;
		}
	}

	if (string_fmts->len > 0 && finfo->hfinfo->strings) {
		g_string_truncate(label_s, 0);
		for (i = 0; i < string_fmts->len; i++) {
			sf = g_ptr_array_index(string_fmts, i);
			if (sf->plain) {
				g_string_append(label_s, sf->plain);
			} else {
				switch (sf->format) {
					case SF_NAME:
						g_string_append(label_s, hfinfo->name);
						break;
					case SF_NUMVAL:
						g_string_append(label_s, fs_ptr);
						break;
					case SF_STRVAL:
						switch(hfinfo->type) {
							case FT_BOOLEAN:
								uvalue = fvalue_get_uinteger(&finfo->value);
								tfstring = (const struct true_false_string*) hfinfo->strings;
								g_string_append(label_s, uvalue ? tfstring->true_string : tfstring->false_string);
								break;
							case FT_INT8:
							case FT_INT16:
							case FT_INT24:
							case FT_INT32:
								DISSECTOR_ASSERT(!hfinfo->bitmask);
								svalue = fvalue_get_sinteger(&finfo->value);
								if (hfinfo->display & BASE_RANGE_STRING) {
								  g_string_append(label_s, rval_to_str(svalue, hfinfo->strings, "Unknown"));
								} else {
								  g_string_append(label_s, val_to_str(svalue, cVALS(hfinfo->strings), "Unknown"));
								}
							case FT_UINT8:
							case FT_UINT16:
							case FT_UINT24:
							case FT_UINT32:
								uvalue = fvalue_get_uinteger(&finfo->value);
								if (!hfinfo->bitmask && hfinfo->display & BASE_RANGE_STRING) {
								  g_string_append(label_s, rval_to_str(uvalue, hfinfo->strings, "Unknown"));
								} else {
								  g_string_append(label_s, val_to_str(uvalue, cVALS(hfinfo->strings), "Unknown"));
								}
								break;
							default:
								break;
						}
						break;
					default:
						break;
				}
			}
		}
		printf(" %u=\"%s\"", cmd_line_index, label_s->str);
		return TRUE;
	}

	if(finfo->value.ftype->val_to_string_repr)
	{
		printf(" %u=\"%s\"", cmd_line_index, fs_ptr);
		return TRUE;
	}

	/*
	 * This field doesn't have an associated value,
	 * e.g. http
	 * We return n.a.
	 */
	printf(" %u=\"n.a.\"", cmd_line_index);
	return TRUE;
}
コード例 #14
0
static int
dissect_pcap_pktdata(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    gint         offset = 0;
    guint32     *link_type;
    guint32      length = 0;
    tvbuff_t    *next_tvb;
    proto_item  *pseudoheader_item;
    proto_tree  *pseudoheader_tree = NULL;
    proto_item  *packet_item;
    proto_tree  *packet_tree;

    DISSECTOR_ASSERT(data);

    link_type = (guint32 *) data;
    pinfo->phdr->pkt_encap = wtap_pcap_encap_to_wtap_encap(*link_type);

    switch (*link_type) {
    case 139:
/* TODO no description for pseudoheader at http://www.tcpdump.org/linktypes.html */
        break;
    case 196:
        length = 5;
        break;
    case 197:
/* TODO no description for pseudoheader at http://www.tcpdump.org/linktypes.html */
        break;
    case 201:
        length = 4;
        break;
    case 204:
        length = 1;
        break;
    case 205:
        length = 1;
        break;
    case 206:
        length = 1;
        break;
    case 209:
        length = 6;
        break;
    case 226:
        length = 24;
        break;
    case 227:
/* TODO no description for pseudoheader at http://www.tcpdump.org/linktypes.html */
        break;
    case 240:
    case 241:
        length = 4;
        break;
    case 244:
        length = 20;
        break;
    case 245:
        length = 20;
        break;
    }

    if (length > 0) {
        pseudoheader_item = proto_tree_add_item(tree, hf_pcap_pktdata_pseudoheader, tvb, offset, length, ENC_NA);
        pseudoheader_tree = proto_item_add_subtree(pseudoheader_item, ett_pcap_pktdata_pseudoheader);
    }

    switch (*link_type) {
    case 201:
        proto_tree_add_item(pseudoheader_tree, hf_pcap_pktdata_pseudoheader_bluetooth_direction, tvb, offset, 4, ENC_BIG_ENDIAN);
        if (tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN) == 0)
            pinfo->p2p_dir = P2P_DIR_SENT;
        else if (tvb_get_guint32(tvb, offset, ENC_BIG_ENDIAN) == 1)
            pinfo->p2p_dir = P2P_DIR_RECV;
        else
            pinfo->p2p_dir = P2P_DIR_UNKNOWN;
        offset += 4;
        break;
    default:
        offset += length;
    }

    next_tvb = tvb_new_subset_remaining(tvb, offset);

    packet_item = proto_tree_add_item(tree, hf_pcap_pktdata_data, tvb, offset, tvb_reported_length(next_tvb), ENC_NA);
    packet_tree = proto_item_add_subtree(packet_item, ett_pcap_pktdata_data);

    offset = dissector_try_uint_new(wtap_encap_table, pinfo->phdr->pkt_encap, next_tvb, pinfo, packet_tree, TRUE, NULL);

    return offset;
}
コード例 #15
0
static int dissect_pbb_addressblock(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint offset, guint maxoffset,
    guint8 addressType, guint8 addressSize) {
  guint8 addr[MAX_ADDR_SIZE];

  guint8 numAddr;
  guint8 address_flags;
  guint8 head_length = 0, tail_length = 0;
  guint block_length = 0, midSize = 0;
  guint block_index = 0, head_index = 0, tail_index = 0, mid_index = 0, prefix_index = 0;

  proto_tree *addr_tree = NULL;
  proto_tree *addrFlags_tree = NULL;
  proto_tree *addrValue_tree = NULL;

  proto_item *addr_item = NULL;
  proto_item *addrFlags_item = NULL;
  proto_item *addrValue_item = NULL;

  int i = 0;

  if (maxoffset - offset < 2) {
    proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset,
        "Not enough octets for minimal addressblock header");
    return tvb_reported_length(tvb);
  }

  DISSECTOR_ASSERT(addressSize <= MAX_ADDR_SIZE);

  memset(addr, 0, addressSize);

  block_length = 2;
  block_index = offset;
  midSize = addressSize;

  numAddr = tvb_get_guint8(tvb, offset++);
  address_flags = tvb_get_guint8(tvb, offset++);

  if ((address_flags & ADDR_HASHEAD) != 0) {
    head_index = offset;

    if (maxoffset - offset <= 0) {
      proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset,
         "Not enough octets for addressblock head");
      return tvb_reported_length(tvb);
    }
    head_length = tvb_get_guint8(tvb, offset++);

    if (head_length > addressSize-1) {
      proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset,
          "address head length is too long");
      return tvb_reported_length(tvb);
    }
    if (maxoffset - offset < head_length) {
      proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset,
          "Not enough octets for addressblock head");
      return tvb_reported_length(tvb);
    }
    tvb_memcpy(tvb, addr, offset, head_length);

    midSize -= head_length;
    block_length += (head_length+1);
    offset += head_length;
  }
  if ((address_flags & ADDR_HASZEROTAIL) != 0) {
    tail_index = offset;

    if (maxoffset - offset <= 0) {
      proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset,
          "Not enough octets for addressblock tail");
      return tvb_reported_length(tvb);
    }
    tail_length = tvb_get_guint8(tvb, offset++);
    if (tail_length > addressSize-1-head_length) {
      proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset,
          "address tail length is too long");
      return tvb_reported_length(tvb);
    }
    midSize -= tail_length;
    block_length++;
  }
  else if ((address_flags & ADDR_HASFULLTAIL) != 0) {
    tail_index = offset;

    if (maxoffset - offset <= 0) {
      proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset,
          "Not enough octets for addressblock tail");
      return tvb_reported_length(tvb);
    }
    tail_length = tvb_get_guint8(tvb, offset++);
    if (tail_length > addressSize-1-head_length) {
      proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset,
          "address tail length is too long");
      return tvb_reported_length(tvb);
    }

    if (maxoffset - offset < tail_length) {
      proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset,
          "Not enough octets for addressblock tail");
      return tvb_reported_length(tvb);
    }
    tvb_memcpy(tvb, &addr[addressSize - tail_length], offset, tail_length);

    midSize -= tail_length;
    block_length += (tail_length+1);
    offset += tail_length;
  }

  mid_index = offset;
  block_length += numAddr * midSize;
  offset += numAddr * midSize;

  if ((address_flags & ADDR_HASSINGLEPRELEN) != 0) {
    prefix_index = offset;
    block_length++;
  }
  else if ((address_flags & ADDR_HASMULTIPRELEN) != 0) {
    prefix_index = offset;
    block_length += numAddr;
  }

  if (maxoffset < block_index + block_length) {
    proto_tree_add_expert_format(tree, pinfo, &ei_packetbb_error, tvb, offset, maxoffset - offset,
        "Not enough octets for address block");
    return maxoffset;
  }

  /* add address tree */
  addr_item = proto_tree_add_item(tree, hf_packetbb_addr, tvb, block_index, block_length, ENC_NA);
  addr_tree = proto_item_add_subtree(addr_item, ett_packetbb_addr);
  proto_item_append_text(addr_item, " (%d addresses)", numAddr);

  /* add num-addr */
  proto_tree_add_item(addr_tree, hf_packetbb_addr_num, tvb, block_index, 1, ENC_BIG_ENDIAN);

  /* add flags */
  addrFlags_item = proto_tree_add_item(addr_tree, hf_packetbb_addr_flags, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
  addrFlags_tree = proto_item_add_subtree(addrFlags_item, ett_packetbb_addr_flags);

  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hashead, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasfulltail, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_haszerotail, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hassingleprelen, tvb, block_index+1, 1, ENC_BIG_ENDIAN);
  proto_tree_add_item(addrFlags_tree, hf_packetbb_addr_flags_hasmultiprelen, tvb, block_index+1, 1, ENC_BIG_ENDIAN);

  if ((address_flags & ADDR_HASHEAD) != 0) {
    /* add head */
    proto_tree_add_item(addr_tree, hf_packetbb_addr_head, tvb, head_index, head_length+1, ENC_NA);
  }

  if ((address_flags & ADDR_HASFULLTAIL) != 0) {
    /* add full tail */
    proto_tree_add_item(addr_tree, hf_packetbb_addr_tail, tvb, tail_index, tail_length+1, ENC_NA);
  }
  else if ((address_flags & ADDR_HASZEROTAIL) != 0) {
    /* add zero tail */
    proto_tree_add_item(addr_tree, hf_packetbb_addr_tail, tvb, tail_index, 1, ENC_NA);
  }
  for (i=0; i<numAddr; i++) {
    guint32 ipv4 = (addr[0] << 24) + (addr[1] << 16) + (addr[2] << 8) + addr[3];
    guint8 prefix = addressSize * 8;

    tvb_memcpy(tvb, &addr[head_length], mid_index + midSize*i, midSize);

    switch (addressType) {
      case 0:
        addrValue_item = proto_tree_add_ipv4(addr_tree, hf_packetbb_addr_value[addressType],
            tvb, mid_index, block_index + block_length - mid_index, ipv4);
        break;
      case 1:
        addrValue_item = proto_tree_add_ipv6(addr_tree, hf_packetbb_addr_value[addressType],
            tvb, mid_index, block_index + block_length - mid_index, (struct e_in6_addr *)addr);
        break;
      case 2:
        addrValue_item = proto_tree_add_ether(addr_tree, hf_packetbb_addr_value[addressType],
            tvb, mid_index, block_index + block_length - mid_index, addr);
        break;
      case 3:
        addrValue_item = proto_tree_add_bytes(addr_tree, hf_packetbb_addr_value[addressType],
            tvb, mid_index, block_index + block_length - mid_index, addr);
        break;
      default:
        break;
    }
    addrValue_tree = proto_item_add_subtree(addrValue_item, ett_packetbb_addr_value);

    proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_mid, tvb,
        mid_index + midSize*i, midSize, ENC_NA);

    if ((address_flags & ADDR_HASSINGLEPRELEN) != 0) {
      prefix = tvb_get_guint8(tvb, prefix_index);
      proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_prefix, tvb, prefix_index, 1, ENC_BIG_ENDIAN);
    }
    else if ((address_flags & ADDR_HASMULTIPRELEN) != 0) {
      prefix = tvb_get_guint8(tvb, prefix_index + i);
      proto_tree_add_item(addrValue_tree, hf_packetbb_addr_value_prefix, tvb, prefix_index + i, 1, ENC_BIG_ENDIAN);
    }
    proto_item_append_text(addrValue_item, "/%d", prefix);
  }

  offset = dissect_pbb_tlvblock(tvb, pinfo, addr_tree, block_index + block_length, maxoffset, numAddr);
  return offset;
}
コード例 #16
0
ファイル: gcp.c プロジェクト: koyeen/wireshark
gcp_ctx_t* gcp_ctx(gcp_msg_t* m, gcp_trx_t* t, guint32 c_id, gboolean persistent) {
    gcp_ctx_t* context = NULL;
    gcp_ctx_t** context_p = NULL;

    if ( !m || !t ) return NULL;

    if (persistent) {

        wmem_tree_key_t ctx_key[4];
        wmem_tree_key_t trx_key[4];

        ctx_key[0].length = 1;
        ctx_key[0].key = &(m->hi_addr);
        ctx_key[1].length = 1;
        ctx_key[1].key = &(m->lo_addr);
        ctx_key[2].length = 1;
        ctx_key[2].key = &(c_id);
        ctx_key[3].length = 0;
        ctx_key[3].key = NULL;

        trx_key[0].length = 1;
        trx_key[0].key = &(m->hi_addr);
        trx_key[1].length = 1;
        trx_key[1].key = &(m->lo_addr);
        trx_key[2].length = 1;
        trx_key[2].key = &(t->id);
        trx_key[3].length = 0;
        trx_key[3].key = NULL;

        if (m->committed) {
            if (( context = (gcp_ctx_t *)wmem_tree_lookup32_array(ctxs_by_trx,trx_key) )) {
                return context;
            } if ((context_p = (gcp_ctx_t **)wmem_tree_lookup32_array(ctxs,ctx_key))) {
                context = *context_p;

                do {
                    if (context->initial->framenum <= m->framenum) {
                        return context;
                    }
                } while(( context = context->prev ));

                DISSECTOR_ASSERT(! "a context should exist");
            }
        } else {
            if (c_id == CHOOSE_CONTEXT) {
                if (! ( context = (gcp_ctx_t *)wmem_tree_lookup32_array(ctxs_by_trx,trx_key))) {
                    context = wmem_new(wmem_file_scope(), gcp_ctx_t);
                    context->initial = m;
                    context->cmds = NULL;
                    context->id = c_id;
                    context->terms.last = &(context->terms);
                    context->terms.next = NULL;
                    context->terms.term = NULL;

                    wmem_tree_insert32_array(ctxs_by_trx,trx_key,context);
                }
            } else {
                if (( context = (gcp_ctx_t *)wmem_tree_lookup32_array(ctxs_by_trx,trx_key) )) {
                    if (( context_p = (gcp_ctx_t **)wmem_tree_lookup32_array(ctxs,ctx_key) )) {
                        if (context != *context_p) {
                            if(context->id != CHOOSE_CONTEXT) {
                                context = wmem_new(wmem_file_scope(), gcp_ctx_t);
                            }
                            context->initial = m;
                            context->id = c_id;
                            context->cmds = NULL;
                            context->terms.last = &(context->terms);
                            context->terms.next = NULL;
                            context->terms.term = NULL;

                            context->prev = *context_p;
                            *context_p = context;
                        }
                    } else {
                        context_p = wmem_new(wmem_file_scope(), gcp_ctx_t*);
                        *context_p = context;
                        context->initial = m;
                        context->id = c_id;
                        wmem_tree_insert32_array(ctxs,ctx_key,context_p);
                    }
                } else if (! ( context_p = (gcp_ctx_t**)wmem_tree_lookup32_array(ctxs,ctx_key) )) {
                    context = wmem_new(wmem_file_scope(), gcp_ctx_t);
                    context->initial = m;
                    context->id = c_id;
                    context->cmds = NULL;
                    context->terms.last = &(context->terms);
                    context->terms.next = NULL;
                    context->terms.term = NULL;

                    context_p = wmem_new(wmem_file_scope(), gcp_ctx_t*);
                    *context_p = context;
                    wmem_tree_insert32_array(ctxs,ctx_key,context_p);
                } else {
                    context = *context_p;
                }
            }
コード例 #17
0
ファイル: stream.c プロジェクト: acaceres2176/wireshark
guint32 stream_get_frag_length( const stream_pdu_fragment_t *frag)
{
    DISSECTOR_ASSERT( frag );
    return frag->len;
}
コード例 #18
0
/*--- dissect_q932_ros -----------------------------------------------------*/
static int dissect_q932_ros(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
  rose_ctx_tmp = get_rose_ctx(pinfo->private_data);
  DISSECTOR_ASSERT(rose_ctx_tmp);
  return dissect_ROS_PDU(tvb, pinfo, tree);
}
コード例 #19
0
ファイル: stream.c プロジェクト: acaceres2176/wireshark
guint32 stream_get_pdu_no( const stream_pdu_fragment_t *frag)
{
    DISSECTOR_ASSERT( frag );
    return frag->pdu->pdu_number;
}
コード例 #20
0
static void dissect_usb_i1d3_command(
        tvbuff_t *tvb, packet_info *pinfo,
        usb_i1d3_conversation_t *conversation, proto_tree *tree) {
    // Parsing the command code is a bit tricky: if the most significant
    // byte is non-zero, the command code is the most significant byte,
    // *and* the next byte is the first byte of the payload.
    guint32 command_code = tvb_get_ntohs(tvb, 0);
    guint32 command_code_msb = command_code & 0xff00;
    gint command_code_length = 2;
    if (command_code_msb) {
        command_code = command_code_msb;
        command_code_length = 1;
    }
    proto_item *command_code_item = proto_tree_add_uint(
            tree, hf_usb_i1d3_command_code, tvb, 0, command_code_length,
            command_code);

    usb_i1d3_transaction_t *transaction;
    if (!PINFO_FD_VISITED(pinfo)) {
        transaction = usb_i1d3_create_transaction(conversation, pinfo->num);
        transaction->command_code = command_code;
    } else {
        transaction = (usb_i1d3_transaction_t *)wmem_map_lookup(
                conversation->request_to_transaction,
                GUINT_TO_POINTER(pinfo->num));
    }
    DISSECTOR_ASSERT(transaction);

    if (transaction->response != 0) {
        proto_item *response_item = proto_tree_add_uint(
                tree, hf_usb_i1d3_response_in, tvb, 0, 0,
                transaction->response);
        PROTO_ITEM_SET_GENERATED(response_item);
    }

    const gchar *command_code_string = try_val_to_str(
            command_code, usb_i1d3_command_code_strings);
    if (command_code_string) {
        col_set_str(pinfo->cinfo, COL_INFO, command_code_string);
    } else {
        expert_add_info(pinfo, command_code_item,
                &ei_usb_i1d3_unknown_command);
        col_set_str(pinfo->cinfo, COL_INFO, "Unknown command");
    }

    switch (command_code) {
        case USB_I1D3_LOCKRESP: {
            // TODO: verify that the challenge response is correct
            proto_tree_add_item(
                    tree, hf_usb_i1d3_challenge_response, tvb, 24, 16, ENC_NA);
            break;
        }

        case USB_I1D3_READINTEE: {
            guint32 offset, length;
            proto_tree_add_item_ret_uint(
                    tree, hf_usb_i1d3_readintee_offset, tvb,
                    1, 1, ENC_NA, &offset);
            proto_tree_add_item_ret_uint(
                    tree, hf_usb_i1d3_readintee_length, tvb,
                    2, 1, ENC_NA, &length);
            col_add_fstr(pinfo->cinfo, COL_INFO, "%s (offset: %u, length: %u)",
                    command_code_string, offset, length);
            if (!PINFO_FD_VISITED(pinfo)) {
                transaction->offset = offset;
                transaction->length = length;
            }
            break;
        }

        case USB_I1D3_READEXTEE: {
            guint32 offset, length;
            proto_tree_add_item_ret_uint(
                    tree, hf_usb_i1d3_readextee_offset, tvb,
                    1, 2, ENC_BIG_ENDIAN, &offset);
            proto_tree_add_item_ret_uint(
                    tree, hf_usb_i1d3_readextee_length, tvb,
                    3, 1, ENC_NA, &length);
            col_add_fstr(pinfo->cinfo, COL_INFO, "%s (offset: %u, length: %u)",
                    command_code_string, offset, length);
            if (!PINFO_FD_VISITED(pinfo)) {
                transaction->offset = offset;
                transaction->length = length;
            }
            break;
        }

        case USB_I1D3_MEASURE1: {
            guint32 integration_time;
            proto_item *integration_time_item = proto_tree_add_item_ret_uint(
                    tree, hf_usb_i1d3_requested_integration_time, tvb, 1, 4,
                    ENC_LITTLE_ENDIAN, &integration_time);
            double integration_time_seconds =
                integration_time / USB_I1D3_CLOCK_FREQUENCY;
            proto_item_append_text(
                    integration_time_item,
                    " [%.6f seconds]", integration_time_seconds);
            col_add_fstr(pinfo->cinfo, COL_INFO,
                    "Measure for %.6fs", integration_time_seconds);
            break;
        }
        case USB_I1D3_MEASURE2: {
            proto_item *edge_count_item = proto_tree_add_item(
                    tree, hf_usb_i1d3_requested_edge_count, tvb, 1, 6, ENC_NA);
            proto_tree *edge_count_tree = proto_item_add_subtree(
                    edge_count_item, ett_usb_i1d3_requested_edge_count);
            guint32 edge_count_red, edge_count_green, edge_count_blue;
            proto_tree_add_item_ret_uint(
                    edge_count_tree, hf_usb_i1d3_requested_edge_count_red, tvb,
                    1, 2, ENC_LITTLE_ENDIAN, &edge_count_red);
            proto_tree_add_item_ret_uint(
                    edge_count_tree, hf_usb_i1d3_requested_edge_count_green, tvb,
                    3, 2, ENC_LITTLE_ENDIAN, &edge_count_green);
            proto_tree_add_item_ret_uint(
                    edge_count_tree, hf_usb_i1d3_requested_edge_count_blue, tvb,
                    5, 2, ENC_LITTLE_ENDIAN, &edge_count_blue);
            proto_item_append_text(
                    edge_count_item, ": R%u G%u B%u",
                    edge_count_red, edge_count_green, edge_count_blue);
            col_add_fstr(pinfo->cinfo, COL_INFO, "Measure R%u G%u B%u edges",
                    edge_count_red, edge_count_green, edge_count_blue);
            break;
        }
        case USB_I1D3_SETLED: {
            guint32 led_mode, led_offtime, led_ontime, pulse_count;
            proto_tree_add_item_ret_uint(
                    tree, hf_usb_i1d3_led_mode, tvb, 1, 1, ENC_NA, &led_mode);
            proto_item *led_offtime_item = proto_tree_add_item_ret_uint(
                    tree, hf_usb_i1d3_led_offtime, tvb, 2, 1, ENC_NA,
                    &led_offtime);
            double led_offtime_seconds =
                led_offtime / USB_I1D3_LED_OFFTIME_FACTOR;
            proto_item_append_text(
                    led_offtime_item, " [%.6f seconds]", led_offtime_seconds);
            proto_item *led_ontime_item = proto_tree_add_item_ret_uint(
                    tree, hf_usb_i1d3_led_ontime, tvb, 3, 1, ENC_NA,
                    &led_ontime);
            double led_ontime_seconds =
                led_ontime / ((led_mode == USB_I1D3_LED_BLINK) ?
                        USB_I1D3_LED_ONTIME_FACTOR :
                        USB_I1D3_LED_ONTIME_FADE_FACTOR);
            proto_item_append_text(
                    led_ontime_item, " [%.6f seconds]", led_ontime_seconds);
            proto_item *pulse_count_item = proto_tree_add_item_ret_uint(
                    tree, hf_usb_i1d3_led_pulse_count, tvb, 4, 1, ENC_NA,
                    &pulse_count);
            if (pulse_count == 0x80) {
                proto_item_append_text(pulse_count_item, " [infinity]");
                col_add_fstr(pinfo->cinfo, COL_INFO,
                        "Pulse LED off (%.6fs) and on (%.6fs%s) "
                        "indefinitely", led_offtime_seconds, led_ontime_seconds,
                        (led_mode == USB_I1D3_LED_BLINK_FADE_ON) ?
                        " fading" : "");
            } else {
                col_add_fstr(pinfo->cinfo, COL_INFO,
                        "Pulse LED off (%.6fs) and on (%.6fs%s) "
                        "%u times", led_offtime_seconds, led_ontime_seconds,
                        (led_mode == USB_I1D3_LED_BLINK_FADE_ON) ?
                        " fading" : "", pulse_count);
            }
        }
    }
}
コード例 #21
0
void
proto_reg_handoff_gsm_sms_ud(void)
{
    wsp_handle = find_dissector("wsp-cl");
    DISSECTOR_ASSERT(wsp_handle);
}
コード例 #22
0
static void dissect_usb_i1d3_response(
        tvbuff_t *tvb, packet_info *pinfo,
        usb_i1d3_conversation_t *conversation, proto_tree *tree) {
    // The response packet does not contain any information about the command
    // it is a response to, so we need to reconstruct this information using the
    // previous packet that we saw.
    //
    // Note: currently, for simplicity's sake, this assumes that there is only
    // one inflight request at any given time - in other words, that there is no
    // pipelining going on. It is not clear if the device would even be able to
    // service more than one request at the same time in the first place.
    usb_i1d3_transaction_t *transaction;
    if (!PINFO_FD_VISITED(pinfo)) {
        transaction = (usb_i1d3_transaction_t *)wmem_map_lookup(
                conversation->request_to_transaction,
                GUINT_TO_POINTER(conversation->previous_packet));
        if (transaction) {
            DISSECTOR_ASSERT(transaction->response == 0);
            transaction->response = pinfo->num;
            wmem_map_insert(
                    conversation->response_to_transaction,
                    GUINT_TO_POINTER(transaction->response),
                    (void *)transaction);
        }
    } else {
        // After the first pass, we can't use previous_packet anymore since
        // there is no guarantee the dissector is called in order, so we use
        // the reverse mapping that we populated above.
        transaction = (usb_i1d3_transaction_t *)wmem_map_lookup(
                conversation->response_to_transaction,
                GUINT_TO_POINTER(pinfo->num));
    }
    if (transaction) {
        DISSECTOR_ASSERT(transaction->response == pinfo->num);
        DISSECTOR_ASSERT(transaction->request != 0);
    }

    proto_item *request_item = proto_tree_add_uint(
            tree, hf_usb_i1d3_request_in, tvb, 0, 0,
            transaction ? transaction->request : 0);
    PROTO_ITEM_SET_GENERATED(request_item);
    if (!transaction) {
        expert_add_info(pinfo, request_item, &ei_usb_i1d3_unexpected_response);
    } else {
        proto_item *command_code_item = proto_tree_add_uint(
                tree, hf_usb_i1d3_command_code, tvb, 0, 0,
                transaction->command_code);
        PROTO_ITEM_SET_GENERATED(command_code_item);
    }

    const gchar *command_string = transaction ? try_val_to_str(
            transaction->command_code, usb_i1d3_command_code_strings) : NULL;
    if (!command_string) command_string = "unknown";

    guint32 response_code;
    proto_item *response_code_item = proto_tree_add_item_ret_uint(
            tree, hf_usb_i1d3_response_code, tvb, 0, 1, ENC_NA, &response_code);
    proto_item_append_text(
            response_code_item, " (%s)", (response_code == 0) ? "OK" : "error");
    if (response_code != 0) {
        col_add_fstr(
                pinfo->cinfo, COL_INFO, "Error code %u (%s)",
                response_code, command_string);
        expert_add_info(pinfo, response_code_item, &ei_usb_i1d3_error);
        return;
    }

    col_add_fstr(pinfo->cinfo, COL_INFO, "OK (%s)", command_string);

    if (!transaction) return;

    // As mentioned in ArgyllCMS spectro/i1d3.c, the second byte is usually the
    // first byte of the command code, except for GET_DIFF.
    if (transaction->command_code != USB_I1D3_GET_DIFF) {
        guint32 echoed_command_code;
        proto_item *echoed_command_code_item = proto_tree_add_item_ret_uint(
                tree, hf_usb_i1d3_echoed_command_code, tvb, 1, 1, ENC_NA,
                &echoed_command_code);
        guint8 expected_command_code = transaction->command_code >> 8;
        proto_item_append_text(
                echoed_command_code_item, " [expected 0x%02x]",
                expected_command_code);
        if (echoed_command_code != expected_command_code) {
            expert_add_info(
                    pinfo, echoed_command_code_item,
                    &ei_usb_i1d3_echoed_command_code_mismatch);
        }
    }
コード例 #23
0
static void
gbl_symbols_array_append(int hash, gchar *symbol) {
  value_string vs = {hash, symbol};
  DISSECTOR_ASSERT(gbl_symbols_array != NULL);
  g_array_append_val(gbl_symbols_array, vs);
}
コード例 #24
0
ファイル: packet-cpfi.c プロジェクト: MichaelQQ/Wireshark-PE
/* Header */
static void
dissect_cpfi_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint32     word1;
#if 0
  guint32     word2;
#endif
  guint32     tda;
  guint32     src;
  guint8      src_instance = 0;
  guint8      src_board    = 0;
  guint8      src_port     = 0;
  guint32     dst;
  guint8      dst_instance = 0;
  guint8      dst_board    = 0;
  guint8      dst_port     = 0;
  proto_tree *extra_tree   = NULL;

  /* add a tree for the header */
  if ( tree != NULL)
  {
    proto_item *extra_item;
    extra_item = proto_tree_add_protocol_format(tree, proto_cpfi, tvb, 0, -1, "Header");
    extra_tree = proto_item_add_subtree(extra_item, ett_cpfi_header);
  }

  /* Extract the common header, and get the bits we need */
  word1 = tvb_get_ntohl (tvb, 0);
#if 0
  word2 = tvb_get_ntohl (tvb, sizeof(word1));
#endif

  /* Figure out where the frame came from. dstTDA is source of frame! */
  tda = (word1 & CPFI_DEST_MASK) >> CPFI_DEST_SHIFT;
  if ( tda >= FIRST_TIO_CARD_ADDRESS )
  {
    g_strlcpy(src_str, " CPFI", sizeof(src_str));
    src = 0;                            /* Make it smallest */
  }
  else
  {
    const guint8 *srcmac;

    /* Make sure this is an Ethernet address. */
    DISSECTOR_ASSERT(pinfo->src.type == AT_ETHER);
    srcmac = (const guint8 *)pinfo->src.data;

    src_instance = srcmac[2]-1;
    src_board = tda >> 4;
    src_port = tda & 0x0f;
    src = (1 << 24)  +  (src_instance << 16) + (src_board << 8) + src_port;
    g_snprintf(src_str, sizeof(src_str), "%u.%u.%u", src_instance, src_board, src_port);
  }

  /* Figure out where the frame is going. srcTDA is destination of frame! */
  tda = (word1 & CPFI_SOURCE_MASK) >> CPFI_SOURCE_SHIFT;
  if ( tda >= FIRST_TIO_CARD_ADDRESS )
  {
    g_strlcpy(dst_str, " CPFI", sizeof(dst_str));
    dst = 0;                            /* Make it smallest */
  }
  else
  {
    const guint8 *dstmac;

    /* Make sure this is an Ethernet address. */
    DISSECTOR_ASSERT(pinfo->dst.type == AT_ETHER);
    dstmac = (const guint8 *)pinfo->dst.data;

    dst_instance = dstmac[2]-1;
    dst_board = tda >> 4;
    dst_port = tda & 0x0f;
    dst = (1 << 24)  +  (dst_instance << 16) + (dst_board << 8) + dst_port;
    g_snprintf(dst_str, sizeof(dst_str), "%u.%u.%u", dst_instance, dst_board, dst_port);
  }

  /* Set up the source and destination and arrow per user configuration. */
  if ( cpfi_arrow_moves  &&  (dst < src) )
  {
    left = dst_str;
    arrow = r_to_l_arrow;
    right = src_str;
  }
  else
  {
    left = src_str;
    arrow = l_to_r_arrow;
    right = dst_str;
  }

  if (extra_tree) {
    proto_item *hidden_item;
    /* For "real" TDAs (i.e. not for microTDAs), add hidden addresses to allow filtering */
    if ( src != 0 )
    {
      hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_instance, tvb, 0, 1, &src_instance);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
      hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_src_instance, tvb, 0, 1, &src_instance);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
      hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_board, tvb, 0, 1, &src_board);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
      hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_src_board, tvb, 0, 1, &src_board);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
      hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_port, tvb, 0, 1, &src_port);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
      hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_src_port, tvb, 0, 1, &src_port);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
    }
    if ( dst != 0 )
    {
      hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_instance, tvb, 0, 1, &dst_instance);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
      hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_dst_instance, tvb, 0, 1, &dst_instance);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
      hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_board, tvb, 0, 1, &dst_board);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
      hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_dst_board, tvb, 0, 1, &dst_board);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
      hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_port, tvb, 0, 1, &dst_port);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
      hidden_item = proto_tree_add_bytes(extra_tree, hf_cpfi_t_dst_port, tvb, 0, 1, &dst_port);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
    }

    /* add word 1 components to the protocol tree */
    proto_tree_add_item(extra_tree, hf_cpfi_word_one  , tvb, 0, 4, ENC_BIG_ENDIAN);

    proto_tree_add_item(extra_tree, hf_cpfi_frame_type, tvb, 0, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(extra_tree, hf_cpfi_source    , tvb, 0, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(extra_tree, hf_cpfi_dest      , tvb, 0, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(extra_tree, hf_cpfi_SOF_type  , tvb, 0, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(extra_tree, hf_cpfi_speed     , tvb, 0, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(extra_tree, hf_cpfi_OPM_error , tvb, 0, 4, ENC_BIG_ENDIAN);
    proto_tree_add_item(extra_tree, hf_cpfi_from_LCM  , tvb, 0, 4, ENC_BIG_ENDIAN);

    /* add word 2 components to the protocol tree */
    proto_tree_add_item(extra_tree, hf_cpfi_word_two  , tvb, 4, 4, ENC_BIG_ENDIAN);
  };
}
コード例 #25
0
ファイル: packet-adb.c プロジェクト: ARK1988/wireshark
static void
save_command(guint32 cmd, guint32 arg0, guint32 arg1, guint32 data_length,
        guint32 crc32, service_data_t *service_data, gint proto, void *data,
        packet_info *pinfo, service_data_t **returned_service_data,
        command_data_t **returned_command_data)
{
    wmem_tree_key_t  key[6];
    guint32          interface_id;
    guint32          bus_id;
    guint32          device_address;
    guint32          side_id;
    guint32          frame_number;
    command_data_t  *command_data;
    wmem_tree_t     *wmem_tree;
    gint             direction = P2P_DIR_UNKNOWN;
    usb_conv_info_t *usb_conv_info = (usb_conv_info_t *) data;

    frame_number = pinfo->fd->num;

    if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID)
        interface_id = pinfo->phdr->interface_id;
    else
        interface_id = 0;

    if (proto == proto_usb) {
        usb_conv_info = (usb_conv_info_t *) data;
        DISSECTOR_ASSERT(usb_conv_info);

        direction = usb_conv_info->direction;

        bus_id             = usb_conv_info->bus_id;
        device_address     = usb_conv_info->device_address;

        key[0].length = 1;
        key[0].key = &interface_id;
        key[1].length = 1;
        key[1].key = &bus_id;
        key[2].length = 1;
        key[2].key = &device_address;
        key[3].length = 1;
        key[3].key = &side_id;
        key[4].length = 1;
        key[4].key = &frame_number;
        key[5].length = 0;
        key[5].key = NULL;
    } else { /* tcp */
        if (pinfo->destport == ADB_TCP_PORT)
            direction = P2P_DIR_SENT;
        else
            direction = P2P_DIR_RECV;

        key[0].length = 1;
        key[0].key = &interface_id;
        key[1].length = 1;
        key[2].length = 1;
        if (direction == P2P_DIR_SENT) {
            key[1].key = &pinfo->srcport;
            key[2].key = &pinfo->destport;
        } else {
            key[1].key = &pinfo->destport;
            key[2].key = &pinfo->srcport;
        }
        key[3].length = 1;
        key[3].key = &side_id;
        key[4].length = 1;
        key[4].key = &frame_number;
        key[5].length = 0;
        key[5].key = NULL;
    }

    if (direction == P2P_DIR_SENT)
        if (cmd == A_CLSE)
            side_id = arg1; /* OUT: local id */
        else
            side_id = arg0; /* OUT: local id */
    else
        side_id = arg1; /* IN: remote id */

    if (cmd == A_OPEN) {
        service_data = wmem_new(wmem_file_scope(), service_data_t);

        service_data->start_in_frame = pinfo->fd->num;
        service_data->close_local_in_frame = max_in_frame;
        service_data->close_remote_in_frame = max_in_frame;

        service_data->local_id = arg0;
        service_data->remote_id = arg1;

        service_data->service = "unknown";

        wmem_tree_insert32_array(service_info, key, service_data);
    }

    command_data = wmem_new(wmem_file_scope(), command_data_t);

    command_data->command = cmd;
    command_data->arg0 = arg0;
    command_data->arg1 = arg1;

    command_data->command_in_frame = pinfo->fd->num;
    command_data->response_in_frame = max_in_frame;

    command_data->crc32 = crc32;
    command_data->data_length = data_length;
    if (data_length == 0)
        command_data->completed_in_frame = pinfo->fd->num;
    else
        command_data->completed_in_frame = max_in_frame;
    command_data->reassemble_data_length = 0;
    command_data->reassemble_data = (guint8 *) wmem_alloc(wmem_file_scope(), command_data->data_length);

    key[3].length = 1;
    key[3].key = &frame_number;
    key[4].length = 0;
    key[4].key = NULL;
    wmem_tree_insert32_array(command_info, key, command_data);

    if (direction == P2P_DIR_SENT)
        if (command_data->command == A_CLSE)
            side_id = command_data->arg1; /* OUT: local id */
        else
            side_id = command_data->arg0; /* OUT: local id */
    else
        side_id = command_data->arg1; /* IN: remote id */

    key[3].length = 1;
    key[3].key = &side_id;
    key[4].length = 0;
    key[4].key = NULL;

    wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key);
    if (wmem_tree) {
        service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
    }

    if (cmd == A_OKAY) {
        if (!service_data) {
            if (direction == P2P_DIR_SENT)
                side_id = command_data->arg0; /* OUT: local id */
            else
                side_id = command_data->arg1; /* IN: remote id */

            wmem_tree = (wmem_tree_t *) wmem_tree_lookup32_array(service_info, key);
            if (wmem_tree) {
                service_data = (service_data_t *) wmem_tree_lookup32_le(wmem_tree, frame_number);
            }
        }

        if  (service_data && service_data->remote_id == 0 && direction == P2P_DIR_RECV) {
            if (direction == P2P_DIR_SENT) {
                service_data->remote_id = arg1;
            } else {
                service_data->remote_id = arg0;
            }

            side_id = service_data->remote_id;

            key[4].length = 1;
            key[4].key = &frame_number;
            key[5].length = 0;
            key[5].key = NULL;

            wmem_tree_insert32_array(service_info, key, service_data);
        }
    } else if (cmd == A_CLSE) {
        if (service_data) {
            if (direction == P2P_DIR_RECV && service_data->local_id == arg1)
                service_data->close_local_in_frame = pinfo->fd->num;
            else if (direction == P2P_DIR_SENT  && service_data->remote_id == arg1)
                service_data->close_remote_in_frame = pinfo->fd->num;
        }
    }

    DISSECTOR_ASSERT(returned_service_data && returned_command_data);
    *returned_service_data = service_data;
    *returned_command_data = command_data;
}
コード例 #26
0
ファイル: value_string.c プロジェクト: ljakab/wireshark
/* Initializes an extended value string. Behaves like a match function to
 * permit lazy initialization of extended value strings.
 * - Goes through the val64_string array to determine the fastest possible
 *   access method.
 * - Verifies that the val64_string contains no NULL string pointers.
 * - Verifies that the val64_string is terminated by {0, NULL}
 */
const val64_string *
_try_val64_to_str_ext_init(const guint64 val, val64_string_ext *vse)
{
    const val64_string *vs_p           = vse->_vs_p;
    const guint         vs_num_entries = vse->_vs_num_entries;

    /* The matching algorithm used:
     * VS_SEARCH   - slow sequential search (as in a normal value string)
     * VS_BIN_TREE - log(n)-time binary search, the values must be sorted
     * VS_INDEX    - constant-time index lookup, the values must be contiguous
     */
    enum { VS_SEARCH, VS_BIN_TREE, VS_INDEX } type = VS_INDEX;

    /* Note: The val64_string 'value' is *unsigned*, but we do a little magic
     * to help with value strings that have negative values.
     *
     * { -3, -2, -1, 0, 1, 2 }
     * will be treated as "ascending ordered" (although it isn't technically),
     * thus allowing constant-time index search
     *
     * { -3, -2, 0, 1, 2 } and { -3, -2, -1, 0, 2 }
     * will both be considered as "out-of-order with gaps", thus falling
     * back to the slow linear search
     *
     * { 0, 1, 2, -3, -2 } and { 0, 2, -3, -2, -1 }
     * will be considered "ascending ordered with gaps" thus allowing
     * a log(n)-time 'binary' search
     *
     * If you're confused, think of how negative values are represented, or
     * google two's complement.
     */

    guint64 prev_value;
    guint64 first_value;
    guint   i;

    DISSECTOR_ASSERT((vs_p[vs_num_entries].value  == 0) &&
                     (vs_p[vs_num_entries].strptr == NULL));

    vse->_vs_first_value = vs_p[0].value;
    first_value          = vs_p[0].value;
    prev_value           = first_value;

    for (i = 0; i < vs_num_entries; i++) {
        DISSECTOR_ASSERT(vs_p[i].strptr != NULL);
        if ((type == VS_INDEX) && (vs_p[i].value != (i + first_value))) {
            type = VS_BIN_TREE;
        }
        /* XXX: Should check for dups ?? */
        if (type == VS_BIN_TREE) {
            if (prev_value > vs_p[i].value) {
                g_warning("Extended value string '%s' forced to fall back to linear search:\n"
                          "  entry %u, value %" G_GINT64_MODIFIER "u [%#" G_GINT64_MODIFIER "x] < previous entry, value %" G_GINT64_MODIFIER "u [%#" G_GINT64_MODIFIER "x]",
                          vse->_vs_name, i, vs_p[i].value, vs_p[i].value, prev_value, prev_value);
                type = VS_SEARCH;
                break;
            }
            if (first_value > vs_p[i].value) {
                g_warning("Extended value string '%s' forced to fall back to linear search:\n"
                          "  entry %u, value %" G_GINT64_MODIFIER "u [%#" G_GINT64_MODIFIER "x] < first entry, value %" G_GINT64_MODIFIER "u [%#" G_GINT64_MODIFIER "x]",
                          vse->_vs_name, i, vs_p[i].value, vs_p[i].value, first_value, first_value);
                type = VS_SEARCH;
                break;
            }
        }

        prev_value = vs_p[i].value;
    }

    switch (type) {
        case VS_SEARCH:
            vse->_vs_match2 = _try_val64_to_str_linear;
            break;
        case VS_BIN_TREE:
            vse->_vs_match2 = _try_val64_to_str_bsearch;
            break;
        case VS_INDEX:
            vse->_vs_match2 = _try_val64_to_str_index;
            break;
        default:
            g_assert_not_reached();
            break;
    }

    return vse->_vs_match2(val, vse);
}
コード例 #27
0
static gint
dissect_hci_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    proto_item     *ttree = NULL;
    proto_tree     *titem = NULL;
    proto_item     *pitem = NULL;
    gint            offset = 0;
    usb_conv_info_t *usb_conv_info = (usb_conv_info_t *)data;
    tvbuff_t       *next_tvb = NULL;
    hci_data_t     *hci_data;
    gint            p2p_dir_save;
    guint32         session_id;
    fragment_head  *reassembled;

    if (tvb_length_remaining(tvb, offset) <= 0)
        return 0;

    titem = proto_tree_add_item(tree, proto_hci_usb, tvb, offset, -1, ENC_NA);
    ttree = proto_item_add_subtree(titem, ett_hci_usb);

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

    DISSECTOR_ASSERT(usb_conv_info);

    p2p_dir_save = pinfo->p2p_dir;
    pinfo->p2p_dir = usb_conv_info->direction;

    switch (pinfo->p2p_dir) {

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

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

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

    session_id = usb_conv_info->bus_id << 16 | usb_conv_info->device_address << 8 | ((pinfo->p2p_dir == P2P_DIR_RECV) ? 1 : 0 ) << 7 | usb_conv_info->endpoint;

    hci_data = (hci_data_t *) wmem_new(wmem_packet_scope(), hci_data_t);
    hci_data->interface_id = HCI_INTERFACE_USB;
    hci_data->adapter_id = usb_conv_info->bus_id << 8 | usb_conv_info->device_address;
    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->ptype = PT_BLUETOOTH;

    next_tvb = tvb_new_subset_remaining(tvb, offset);
    if (!pinfo->fd->flags.visited && usb_conv_info->endpoint <= 0x02) {
        fragment_info_t  *fragment_info;

        fragment_info = (fragment_info_t *) wmem_tree_lookup32(fragment_info_table, session_id);
        if (fragment_info == NULL) {
            fragment_info = (fragment_info_t *) wmem_new(wmem_file_scope(), fragment_info_t);
            fragment_info->fragment_id = 0;
            fragment_info->remaining_length = 0;

            wmem_tree_insert32(fragment_info_table, session_id, fragment_info);
        }

        if (fragment_info->fragment_id == 0) {
            switch(usb_conv_info->endpoint)
            {
            case 0:
                fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 2) + 3;
                break;
            case 1:
                fragment_info->remaining_length = tvb_get_guint8(tvb, offset + 1) + 2;
                break;
            case 2:
                fragment_info->remaining_length = tvb_get_letohs(tvb, offset + 2) + 4;
                break;
            }
        }

        fragment_info->remaining_length -= tvb_ensure_length_remaining(tvb, offset);

        fragment_add_seq_check(&hci_usb_reassembly_table,
                               tvb, offset, pinfo, session_id, NULL,
                               fragment_info->fragment_id, tvb_length_remaining(tvb, offset), (fragment_info->remaining_length == 0) ? FALSE : TRUE);
        if (fragment_info->remaining_length > 0)
            fragment_info->fragment_id += 1;
        else
            fragment_info->fragment_id = 0;
    }

    reassembled = fragment_get_reassembled_id(&hci_usb_reassembly_table, pinfo, session_id);
    if (reassembled && pinfo->fd->num < reassembled->reassembled_in) {
        pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_fragment, tvb, offset, -1, ENC_NA);
        PROTO_ITEM_SET_GENERATED(pitem);

        col_append_str(pinfo->cinfo, COL_INFO, " Fragment");
    } else if (reassembled && pinfo->fd->num == reassembled->reassembled_in) {
        pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_complete, tvb, offset, -1, ENC_NA);
        PROTO_ITEM_SET_GENERATED(pitem);

        if (reassembled->len > tvb_ensure_length_remaining(tvb, offset)) {
            next_tvb = process_reassembled_data(tvb, 0, pinfo,
                    "Reassembled HCI_USB",
                    reassembled, &hci_usb_msg_frag_items,
                    NULL, ttree);
        }

        switch(usb_conv_info->endpoint)
        {
        case 0:
            call_dissector_with_data(bthci_cmd_handle, next_tvb, pinfo, tree, hci_data);
            break;
        case 1:
            call_dissector_with_data(bthci_evt_handle, next_tvb, pinfo, tree, hci_data);
            break;
        case 2:
            call_dissector_with_data(bthci_acl_handle, next_tvb, pinfo, tree, hci_data);
            break;
        }
    } else {
        pitem = proto_tree_add_item(ttree, hf_bthci_usb_packet_unknown_fragment, tvb, offset, -1, ENC_NA);
        PROTO_ITEM_SET_GENERATED(pitem);
    }

    if (usb_conv_info->endpoint == 0x03) {
        call_dissector_with_data(bthci_sco_handle, next_tvb, pinfo, tree, hci_data);
    } else if (usb_conv_info->endpoint > 0x03) {
        proto_tree_add_item(ttree, hf_bthci_usb_data, tvb, offset, -1, ENC_NA);
    }

    offset += tvb_length_remaining(tvb, offset);

    pinfo->p2p_dir = p2p_dir_save;

    return offset;
}
コード例 #28
0
ファイル: packet-mndp.c プロジェクト: dogphilly/wireshark
static int
dissect_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mndp_tree,
	guint32 offset, guint32 length _U_, const ext_value_string *value_array)
{
	guint32 tlv_type;
	guint32 tlv_length;
	proto_item *tlv_item;
	proto_item *tlv_tree;
	proto_item *type_item;
	int type_index;
	guint32 tlv_end;
	guint encoding_info;

	tlv_type = tvb_get_ntohs(tvb, offset);
	tlv_length = tvb_get_ntohs(tvb, offset + 2);
	/* DISSECTOR_ASSERT(tlv_length >= 4); */
	tlv_item = proto_tree_add_text(mndp_tree, tvb,
		offset, tlv_length+4,
		"T %d, L %d: %s",
		tlv_type,
		tlv_length,
		extval_to_str_idx(tlv_type, value_array, NULL, "Unknown"));
	tlv_tree = proto_item_add_subtree(tlv_item,
		ett_mndp_tlv_header);
	type_item = proto_tree_add_item(tlv_tree, hf_mndp_tlv_type,
		tvb, offset, 2, ENC_BIG_ENDIAN);
	proto_item_append_text(type_item, " = %s",
		extval_to_str_idx(tlv_type, value_array,
			&type_index, "Unknown"));
	offset += 2;
	proto_tree_add_item(tlv_tree, hf_mndp_tlv_length,
		tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;

	/* tlv_length -= 4; */

	if (tlv_length == 0)
		return offset;

	tlv_end = offset + tlv_length;

	/* Make hf_ handling independent of specialfuncion */
	/* FIXME: Properly handle encoding info */
	if ( type_index != -1
		 && !value_array[type_index].specialfunction
		 && value_array[type_index].evs != NULL
	) {
		encoding_info = value_array[type_index].evs ? TRUE : FALSE;
	} else {
		encoding_info = FALSE;
	}
	if ( type_index != -1 && value_array[type_index].hf_element) {
		proto_tree_add_item(tlv_tree,
			*(value_array[type_index].hf_element),
			tvb, offset, tlv_length, encoding_info);
	} else {
		proto_tree_add_item(tlv_tree, hf_mndp_tlv_data,
			tvb, offset, tlv_length, ENC_NA);
	}
	if ( type_index != -1 && value_array[type_index].specialfunction ) {
		guint32 newoffset;

		while (offset < tlv_end) {
			newoffset = value_array[type_index].specialfunction (
				tvb, pinfo, tlv_tree, offset, tlv_length,
				value_array[type_index].evs);
			DISSECTOR_ASSERT(newoffset > offset);
			offset = newoffset;
		}
	}
	return tlv_end;
}
コード例 #29
0
ファイル: gcp.c プロジェクト: AkhilaAG/gluster-wireshark-1.4
gcp_trx_t* gcp_trx(gcp_msg_t* m ,guint32 t_id , gcp_trx_type_t type, gboolean keep_persistent_data) {
    gcp_trx_t* t = NULL;
    gcp_trx_msg_t* trxmsg;

    if ( !m ) return NULL;

    if (keep_persistent_data) {
        if (m->commited) {

            for ( trxmsg = m->trxs; trxmsg; trxmsg = trxmsg->next) {
                if (trxmsg->trx && trxmsg->trx->id == t_id) {
                    return trxmsg->trx;
                }
            }
            DISSECTOR_ASSERT_NOT_REACHED();
        } else {
            emem_tree_key_t key[] = {
                {1,&(m->hi_addr)},
                {1,&(m->lo_addr)},
                {1,&(t_id)},
                {0,NULL}
            };

            trxmsg = se_alloc(sizeof(gcp_trx_msg_t));
            t = se_tree_lookup32_array(trxs,key);

            if (!t) {
                t = se_alloc(sizeof(gcp_trx_t));
                t->initial = m;
                t->id = t_id;
                t->type = type;
                t->pendings = 0;
                t->error = 0;
                t->cmds = NULL;

                se_tree_insert32_array(trxs,key,t);
            }

            /* XXX: request, reply and ack + point to frames where they are */
            switch ( type ) {
                case GCP_TRX_PENDING:
                    t->pendings++;
                    break;
                default:
                    break;
            }

        }
    } else {
        t = ep_new(gcp_trx_t);
        trxmsg = ep_new(gcp_trx_msg_t);
        t->initial = NULL;
        t->id = t_id;
        t->type = type;
        t->pendings = 0;
        t->error = 0;
        t->cmds = NULL;
    }

    DISSECTOR_ASSERT(trxmsg);

    trxmsg->trx = t;
    trxmsg->next = NULL;
    trxmsg->last = trxmsg;

    if (m->trxs) {
        m->trxs->last = m->trxs->last->next = trxmsg;
    } else {
        m->trxs = trxmsg;
    }

    return t;
}
コード例 #30
0
static gint
dissect_adb_service(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    proto_item          *main_item;
    proto_tree          *main_tree;
    proto_item          *sub_item;
    proto_tree          *sub_tree;
    gint                 offset = 0;
    adb_service_data_t  *adb_service_data = (adb_service_data_t *) data;
    const guint8        *service;
    wmem_tree_key_t      key[5];
    wmem_tree_t         *subtree;
    guint32              i_key;

    main_item = proto_tree_add_item(tree, proto_adb_service, tvb, offset, -1, ENC_NA);
    main_tree = proto_item_add_subtree(main_item, ett_adb_service);

    DISSECTOR_ASSERT(adb_service_data);

    service = adb_service_data->service;

    sub_item = proto_tree_add_string(main_tree, hf_service, tvb, offset, 0, service);
    PROTO_ITEM_SET_GENERATED(sub_item);

        if (g_strcmp0(service, "host:version") == 0) {
            guint32               version;
            guint32               data_length;
            continuation_data_t  *continuation_data;

            DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
            for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
                key[i_key].length = 1;
                key[i_key].key = &adb_service_data->session_key[i_key];
            }
            key[i_key].length = 0;
            key[i_key].key = NULL;

            subtree = (wmem_tree_t *) wmem_tree_lookup32_array(continuation_infos, key);
            continuation_data = (subtree) ? (continuation_data_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
            if (continuation_data && continuation_data->completed_in_frame < pinfo->num)
                continuation_data = NULL;

            if (!continuation_data || (continuation_data && continuation_data->length_in_frame == pinfo->num))
                offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);

            if (!pinfo->fd->flags.visited && !continuation_data && tvb_reported_length_remaining(tvb, offset) < 4) {
                key[i_key].length = 1;
                key[i_key++].key = &pinfo->num;
                key[i_key].length = 0;
                key[i_key].key = NULL;

                continuation_data = wmem_new(wmem_file_scope(), continuation_data_t);
                continuation_data->length_in_frame = pinfo->num;
                continuation_data->completed_in_frame = G_MAXUINT32;
                continuation_data->length = data_length;

                wmem_tree_insert32_array(continuation_infos, key, continuation_data);
                continuation_data = NULL;
            }

            if (tvb_reported_length_remaining(tvb, offset) >= 4 ||
                        (continuation_data && continuation_data->completed_in_frame == pinfo->num)) {
                if (!pinfo->fd->flags.visited && continuation_data) {
                    continuation_data->completed_in_frame = pinfo->num;
                }
                offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_version, ett_version, hf_version, tvb, offset, &version);

                col_append_fstr(pinfo->cinfo, COL_INFO, " Version=%u", version);
            }

        } else if (g_strcmp0(service, "host:devices") == 0 ||
                g_strcmp0(service, "host:devices-l") == 0 ||
                g_strcmp0(service, "host:track-devices") == 0) {
            guint32  data_length;

            offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);

            sub_item = proto_tree_add_item(main_tree, hf_devices, tvb, offset, -1, ENC_NA | ENC_ASCII);
            if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) {
                expert_add_info(pinfo, sub_item, &ei_incomplete_message);
            }
        } else if (g_strcmp0(service, "host:get-state") == 0 ||
                g_strcmp0(service, "host:get-serialno") == 0 ||
                g_strcmp0(service, "host:get-devpath") == 0 ||
                g_str_has_prefix(service, "connect:") ||
                g_str_has_prefix(service, "disconnect:")) {
            guint32  data_length;

            offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);

            sub_item = proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_NA | ENC_ASCII);
            if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) {
                expert_add_info(pinfo, sub_item, &ei_incomplete_message);
            }
        } else if (g_str_has_prefix(service, "framebuffer:")) {
            framebuffer_data_t  *framebuffer_data = NULL;

            DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
            for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
                key[i_key].length = 1;
                key[i_key].key = &adb_service_data->session_key[i_key];
            }
            key[i_key].length = 0;
            key[i_key].key = NULL;

            subtree = (wmem_tree_t *) wmem_tree_lookup32_array(framebuffer_infos, key);
            framebuffer_data = (subtree) ? (framebuffer_data_t *) wmem_tree_lookup32_le(subtree, pinfo->num) : NULL;
            if (framebuffer_data && framebuffer_data->completed_in_frame < pinfo->num)
                framebuffer_data = NULL;

            if (!pinfo->fd->flags.visited && !framebuffer_data) {
                key[i_key].length = 1;
                key[i_key++].key = &pinfo->num;
                key[i_key].length = 0;
                key[i_key].key = NULL;

                framebuffer_data = wmem_new(wmem_file_scope(), framebuffer_data_t);
                framebuffer_data->data_in      = pinfo->num;
                framebuffer_data->current_size = 0;
                framebuffer_data->completed_in_frame = G_MAXUINT32;
                framebuffer_data->size         = tvb_get_letohl(tvb, offset + 4 * 2);
                framebuffer_data->red_offset   = tvb_get_letohl(tvb, offset + 4 * 5);
                framebuffer_data->red_length   = tvb_get_letohl(tvb, offset + 4 * 6);
                framebuffer_data->green_offset = tvb_get_letohl(tvb, offset + 4 * 7);
                framebuffer_data->green_length = tvb_get_letohl(tvb, offset + 4 * 8);
                framebuffer_data->blue_offset  = tvb_get_letohl(tvb, offset + 4 * 9);
                framebuffer_data->blue_length  = tvb_get_letohl(tvb, offset + 4 * 10);
                framebuffer_data->alpha_offset = tvb_get_letohl(tvb, offset + 4 * 11);
                framebuffer_data->alpha_length = tvb_get_letohl(tvb, offset + 4 * 12);

                wmem_tree_insert32_array(framebuffer_infos, key, framebuffer_data);
            }

            if (framebuffer_data && framebuffer_data->data_in == pinfo->num) {
                proto_tree_add_item(main_tree, hf_framebuffer_version, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_depth, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_size, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_width, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_height, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_red_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_red_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_blue_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_blue_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_green_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_green_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_alpha_offset, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;

                proto_tree_add_item(main_tree, hf_framebuffer_alpha_length, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                offset += 4;
            }

            if (tvb_reported_length_remaining(tvb, offset) > 0) {
                sub_item = proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
                sub_tree = proto_item_add_subtree(sub_item, ett_data);

                if (!pinfo->fd->flags.visited && framebuffer_data) {
                    framebuffer_data->current_size += tvb_captured_length_remaining(tvb, offset);
                    if (framebuffer_data->current_size >= framebuffer_data->size)
                        framebuffer_data->completed_in_frame = pinfo->num;
                }

                if (pref_dissect_more_detail_framebuffer) {
                    proto_item  *pixel_item;
                    proto_tree  *pixel_tree;

                    if (framebuffer_data &&
                        framebuffer_data->red_length == 5 &&
                        framebuffer_data->green_length == 6 &&
                        framebuffer_data->blue_length == 5 &&
                        framebuffer_data->red_offset == 11 &&
                        framebuffer_data->green_offset == 5 &&
                        framebuffer_data->blue_offset == 0) {
                        while (tvb_reported_length_remaining(tvb, offset) > 0) {
                            if (tvb_reported_length_remaining(tvb, offset) < 2) {
                                proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA);
                                offset += 1;
                            }

                            pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 2, ENC_NA);
                            pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel);

                            proto_tree_add_item(pixel_tree, hf_framebuffer_blue_5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                            proto_tree_add_item(pixel_tree, hf_framebuffer_green_6, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                            proto_tree_add_item(pixel_tree, hf_framebuffer_red_5, tvb, offset, 2, ENC_LITTLE_ENDIAN);
                            offset += 2;
                        }
                    } else if (framebuffer_data &&
                            framebuffer_data->red_length == 8 &&
                            framebuffer_data->green_length == 8 &&
                            framebuffer_data->blue_length == 8 &&
                            (framebuffer_data->alpha_length == 0 ||
                            framebuffer_data->alpha_length == 8)) {
                        while (tvb_reported_length_remaining(tvb, offset) > 0) {
                            if (tvb_reported_length_remaining(tvb, offset) < 3 || (tvb_reported_length_remaining(tvb, offset) < 4 && framebuffer_data->alpha_offset > 0)) {
                                proto_tree_add_item(main_tree, hf_fragment, tvb, offset, -1, ENC_NA);
                                offset = tvb_captured_length(tvb);
                                break;
                            }

                            pixel_item = proto_tree_add_item(sub_tree, hf_framebuffer_pixel, tvb, offset, 3, ENC_NA);
                            pixel_tree = proto_item_add_subtree(pixel_item, ett_pixel);

                            proto_tree_add_item(pixel_tree, hf_framebuffer_red, tvb, offset + framebuffer_data->red_offset / 8, 1, ENC_LITTLE_ENDIAN);
                            proto_tree_add_item(pixel_tree, hf_framebuffer_green, tvb, offset + framebuffer_data->green_offset / 8, 1, ENC_LITTLE_ENDIAN);
                            proto_tree_add_item(pixel_tree, hf_framebuffer_blue, tvb, offset + framebuffer_data->blue_offset / 8, 1, ENC_LITTLE_ENDIAN);

                            if (framebuffer_data->alpha_offset > 0) {
                                if (framebuffer_data->alpha_length == 0)
                                    proto_tree_add_item(pixel_tree, hf_framebuffer_unused, tvb, offset + framebuffer_data->alpha_offset / 8, 1, ENC_LITTLE_ENDIAN);
                                else
                                    proto_tree_add_item(pixel_tree, hf_framebuffer_alpha, tvb, offset + framebuffer_data->alpha_offset / 8, 1, ENC_LITTLE_ENDIAN);
                                offset += 1;
                                proto_item_set_len(pixel_item, 4);
                            }
                            offset += 3;
                        }
                    } else {
                        offset = tvb_captured_length(tvb);
                    }
                } else {
                    offset = tvb_captured_length(tvb);
                }
            }
        } else if (g_strcmp0(service, "track-jdwp") == 0) {
            guint32  data_length;

            offset = dissect_ascii_uint32(main_tree, hf_hex_ascii_length, ett_length, hf_length, tvb, offset, &data_length);

            if (tvb_reported_length_remaining(tvb, offset) > 0) {
                sub_item = proto_tree_add_item(main_tree, hf_pids, tvb, offset, -1, ENC_NA | ENC_ASCII);
                if ((gint64) data_length < tvb_reported_length_remaining(tvb, offset)) {
                    expert_add_info(pinfo, sub_item, &ei_incomplete_message);
                }
            }
            offset = tvb_captured_length(tvb);
        } else if ((g_strcmp0(service, "shell:export ANDROID_LOG_TAGS=\"\" ; exec logcat -B") == 0) ||
                (g_strcmp0(service, "shell:logcat -B") == 0)) {
            tvbuff_t    *next_tvb;
            tvbuff_t    *new_tvb;
            guint8      *buffer = NULL;
            gint         size = 0;
            gint         i_offset = offset;
            gint         old_offset;
            gint         i_char = 0;
            guint8       c1;
            guint8       c2 = '\0';
            guint16      payload_length;
            guint16      try_header_size;
            gint         logcat_length = 0;
            fragment_t  *fragment;

            DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 1 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
            for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
                key[i_key].length = 1;
                key[i_key].key = &adb_service_data->session_key[i_key];
            }
            key[i_key].length = 0;
            key[i_key].key = NULL;

            subtree = (wmem_tree_t *) wmem_tree_lookup32_array(fragments, key);
            fragment = (subtree) ? (fragment_t *) wmem_tree_lookup32_le(subtree, pinfo->num - 1) : NULL;
            if (fragment) {
                if (!pinfo->fd->flags.visited && fragment->reassembled_in_frame == -1)
                    fragment->reassembled_in_frame = pinfo->num;

                if (fragment->reassembled_in_frame == pinfo->num) {
                    size += fragment->length;
                    i_char += fragment->length;
                }
            }

            size += tvb_reported_length_remaining(tvb, i_offset);
            if (size > 0) {
                buffer = (guint8 *) wmem_alloc(pinfo->pool, size);
                if (fragment && i_char > 0)
                    memcpy(buffer, fragment->data, i_char);

                if (i_char >= 1 && buffer[i_char - 1] == '\r' && tvb_get_guint8(tvb, i_offset) == '\n') {
                    buffer[i_char - 1] = '\n';
                    i_offset += 1;
                }

                c1 = tvb_get_guint8(tvb, i_offset);
                i_offset += 1;
                old_offset = i_offset;

                while (tvb_reported_length_remaining(tvb, i_offset) > 0) {
                    c2 = tvb_get_guint8(tvb, i_offset);

                    if (c1 == '\r' && c2 == '\n') {
                        buffer[i_char] = c2;
                        if (tvb_reported_length_remaining(tvb, i_offset) > 1) {
                            c1 = tvb_get_guint8(tvb, i_offset + 1);
                            i_offset += 2;
                            i_char += 1;
                        } else {
                            i_offset += 1;
                        }

                        continue;
                    }

                    buffer[i_char] = c1;
                    c1 = c2;
                    i_char += 1;
                    i_offset += 1;
                }

                if (tvb_reported_length_remaining(tvb, old_offset) == 0) {
                    buffer[i_char] = c1;
                    i_char += 1;
                } else if (tvb_reported_length_remaining(tvb, old_offset) > 0) {
                    buffer[i_char] = c2;
                    i_char += 1;
                }

                next_tvb = tvb_new_child_real_data(tvb, buffer, i_char, i_char);
                add_new_data_source(pinfo, next_tvb, "Logcat");

                i_offset = 0;
                while (tvb_reported_length_remaining(next_tvb, i_offset) > 0) {
                    if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4) {
                        payload_length = tvb_get_letohs(next_tvb, i_offset);
                        try_header_size = tvb_get_letohs(next_tvb, i_offset + 2);

                        if (try_header_size != 24)
                            logcat_length = payload_length + 20;
                        else
                            logcat_length = payload_length + 24;
                    }

                    if (tvb_reported_length_remaining(next_tvb, i_offset) >= 4 && tvb_reported_length_remaining(next_tvb, i_offset) >= logcat_length) {
                        new_tvb = tvb_new_subset_length(next_tvb, i_offset, logcat_length);

                        call_dissector(logcat_handle, new_tvb, pinfo, main_tree);
                        i_offset += logcat_length;
                    } else {

                        if (!pinfo->fd->flags.visited) {
                            DISSECTOR_ASSERT_HINT(adb_service_data->session_key_length + 2 <= sizeof(key) / sizeof(key[0]), "Tree session key is too small");
                            for (i_key = 0; i_key < adb_service_data->session_key_length; i_key += 1) {
                                key[i_key].length = 1;
                                key[i_key].key = &adb_service_data->session_key[i_key];
                            }
                            key[i_key].length = 1;
                            key[i_key++].key = &pinfo->num;
                            key[i_key].length = 0;
                            key[i_key].key = NULL;

                            fragment = wmem_new(wmem_file_scope(), fragment_t);

                            fragment->length = tvb_captured_length_remaining(next_tvb, i_offset);
                            fragment->data = (guint8 *) wmem_alloc(wmem_file_scope(), fragment->length);
                            tvb_memcpy(next_tvb, fragment->data, i_offset, fragment->length);
                            fragment->reassembled_in_frame = -1;

                            wmem_tree_insert32_array(fragments, key, fragment);
                        }

                        proto_tree_add_item(main_tree, hf_fragment, next_tvb, i_offset, -1, ENC_NA);
                        i_offset = tvb_captured_length(next_tvb);
                    }
                }
            }

            offset = tvb_captured_length(tvb);
        } else if (g_str_has_prefix(service, "shell:")) {
            if (adb_service_data->direction == P2P_DIR_SENT) {
                proto_tree_add_item(main_tree, hf_stdin, tvb, offset, -1, ENC_NA | ENC_ASCII);
                col_append_fstr(pinfo->cinfo, COL_INFO, " Stdin=<%s>", tvb_format_text_wsp(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset)));

            } else {
                proto_tree_add_item(main_tree, hf_stdout, tvb, offset, -1, ENC_NA | ENC_ASCII);
                col_append_fstr(pinfo->cinfo, COL_INFO, " Stdout=<%s>", tvb_format_text_wsp(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset)));
            }
            offset = tvb_captured_length(tvb);
        } else if (g_str_has_prefix(service, "jdwp:")) {
/* TODO */
            proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
            offset = tvb_captured_length(tvb);
        } else if (g_str_has_prefix(service, "sync:")) {
/* TODO */
            proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
            offset = tvb_captured_length(tvb);
        } else if (g_strcmp0(service, "host:list-forward") == 0 ||
                g_str_has_prefix(service, "root:") ||
                g_str_has_prefix(service, "remount:")  ||
                g_str_has_prefix(service, "tcpip:")  ||
                g_str_has_prefix(service, "usb:")) {
            if (tvb_reported_length_remaining(tvb, offset)) {
                proto_tree_add_item(main_tree, hf_result, tvb, offset, -1, ENC_NA | ENC_ASCII);
                col_append_fstr(pinfo->cinfo, COL_INFO, " Result=<%s>", tvb_format_text_wsp(wmem_packet_scope(), tvb, offset, tvb_captured_length_remaining(tvb, offset)));

                offset = tvb_captured_length(tvb);
            }
        } else {
            proto_tree_add_item(main_tree, hf_data, tvb, offset, -1, ENC_NA);
            offset = tvb_captured_length(tvb);
        }

    return offset;
}