Exemple #1
0
static void
add_request(ipmi_packet_data_t * data, const ipmi_header_t * hdr)
{
	/* get current frame */
	ipmi_frame_data_t * rq_frame = data->curr_frame;

	/* get current command data */
	ipmi_cmd_data_t * rq_data = rq_frame->cmd_data[data->curr_level];

	/* check if parse response for the first time */
	if (!rq_data) {
		ipmi_request_t * rq;

		/* allocate command data */
		rq_data = wmem_new0(wmem_file_scope(), ipmi_cmd_data_t);

		/* set command data pointer */
		rq_frame->cmd_data[data->curr_level] = rq_data;

		/* allocate request data */
		rq = wmem_new0(wmem_file_scope(), ipmi_request_t);

		/* copy request header */
		memcpy(&rq->hdr, hdr, sizeof(rq->hdr));

		/* override context, channel and direction */
		rq->hdr.context = 0;
		rq->hdr.channel = data->curr_channel;
		rq->hdr.dir = data->curr_dir;

		/* set request frame number */
		rq->frame_num = data->curr_frame_num;

		/* set command nest level */
		rq->nest_level = data->curr_level;

		/* append request to list */
		wmem_list_append(data->request_list, rq);

#ifdef DEBUG
	fprintf(stderr, "%d, %d: hdr : {\n"
			"\tchannel=%d\n"
			"\tdir=%d\n"
			"\trs_sa=%x\n"
			"\trs_lun=%d\n"
			"\tnetfn=%x\n"
			"\trq_sa=%x\n"
			"\trq_lun=%d\n"
			"\trq_seq=%x\n"
			"\tcmd=%x\n}\n",
			data->curr_frame_num, data->curr_level,
			rq->hdr.channel, rq->hdr.dir, rq->hdr.rs_sa, rq->hdr.rs_lun,
			rq->hdr.netfn, rq->hdr.rq_sa, rq->hdr.rq_lun, rq->hdr.rq_seq,
			rq->hdr.cmd);
#endif
	}
}
/* split out some common FEC handling */
static guint dissect_feccode(proto_tree *tree, tvbuff_t *tvb, guint offset,
                             packet_info *pinfo, gint reserved)
{
    norm_packet_data_t *norm_data;
    guint8              encoding_id = tvb_get_guint8(tvb, offset);

    /* Save encoding ID */
    norm_data = wmem_new0(wmem_file_scope(), norm_packet_data_t);
    norm_data->encoding_id = encoding_id;

    p_add_proto_data(wmem_file_scope(), pinfo, proto_rmt_norm, 0, norm_data);

    proto_tree_add_item(tree, hf_fec_encoding_id, tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1;
    if (reserved) {
        proto_tree_add_item(tree, hf_reserved, tvb, offset, 1, ENC_NA); offset += 1;
    }
    proto_tree_add_item(tree, hf_object_transport_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset+=2;

    if (tvb_reported_length_remaining(tvb, offset) > 0) {
        fec_data_exchange_t  fec;
        tvbuff_t            *new_tvb;
        int                  len;

        new_tvb = tvb_new_subset_remaining(tvb, offset);

        fec.encoding_id = encoding_id;
        len = call_dissector_with_data(rmt_fec_handle, new_tvb, pinfo, tree, &fec);
        if (len > 0)
            offset += len;
    }

    return offset;
}
Exemple #3
0
static ipmi_packet_data_t *
get_packet_data(packet_info * pinfo)
{
	ipmi_packet_data_t * data;

	/* get conversation data */
	conversation_t * conv = find_or_create_conversation(pinfo);

	/* get protocol-specific data */
	data = (ipmi_packet_data_t *)
			conversation_get_proto_data(conv, proto_ipmi);

	if (!data) {
		/* allocate per-packet data */
		data = wmem_new0(wmem_file_scope(), ipmi_packet_data_t);

		/* allocate request list and frame tree */
		data->frame_tree = wmem_tree_new(wmem_file_scope());
		data->request_list = wmem_list_new(wmem_file_scope());

		/* add protocol data */
		conversation_add_proto_data(conv, proto_ipmi, data);
	}

	/* check if packet has changed */
	if (pinfo->num != data->curr_frame_num) {
		data->curr_level = 0;
		data->next_level = 0;
	}

	return data;
}
/* code to dissect NORM info packets */
static void dissect_norm_info(proto_tree *tree, packet_info *pinfo, tvbuff_t *tvb, guint offset, guint8 hlen)
{
    proto_item         *ti;
    proto_tree         *flag_tree;
    norm_packet_data_t *norm_data;

    offset = dissect_grrtetc(tree, tvb, offset);

    ti = proto_tree_add_item(tree, hf_flags, tvb, offset, 1, ENC_BIG_ENDIAN);
    flag_tree = proto_item_add_subtree(ti, ett_flags);
    proto_tree_add_item(flag_tree, hf_flag_repair,        tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(flag_tree, hf_flag_norm_explicit, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(flag_tree, hf_flag_info,          tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(flag_tree, hf_flag_unreliable,    tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(flag_tree, hf_flag_file,          tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(flag_tree, hf_flag_stream,        tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(flag_tree, hf_flag_msgstart,      tvb, offset, 1, ENC_BIG_ENDIAN);
    offset += 1;

    /* Save encoding ID */
    norm_data = wmem_new0(wmem_file_scope(), norm_packet_data_t);
    norm_data->encoding_id = tvb_get_guint8(tvb, offset);

    p_add_proto_data(wmem_file_scope(), pinfo, proto_rmt_norm, 0, norm_data);

    proto_tree_add_item(tree, hf_fec_encoding_id,     tvb, offset, 1, ENC_BIG_ENDIAN); offset += 1;
    proto_tree_add_item(tree, hf_object_transport_id, tvb, offset, 2, ENC_BIG_ENDIAN); offset += 2;

    if (offset < hdrlen2bytes(hlen)) {
        offset = dissect_norm_hdrext(tree, pinfo, tvb, offset, hlen);
    }
    if (tvb_reported_length_remaining(tvb, offset) > 0)
        proto_tree_add_item(tree, hf_payload, tvb, offset, -1, ENC_NA);
}
static ulp_private_data_t* ulp_get_private_data(asn1_ctx_t *actx)
{
  if (actx->private_data == NULL) {
    actx->private_data = wmem_new0(wmem_packet_scope(), ulp_private_data_t);
  }
  return (ulp_private_data_t*)actx->private_data;
}
Exemple #6
0
void asn1_stack_frame_push(asn1_ctx_t *actx, const gchar *name) {
  asn1_stack_frame_t *frame;

  frame = wmem_new0(wmem_packet_scope(), asn1_stack_frame_t);
  frame->name = name;
  frame->next = actx->stack;
  actx->stack = frame;
}
/* Generic Extensible Framework */
gef_ctx_t* gef_ctx_alloc(gef_ctx_t *parent, const gchar *type) {
  gef_ctx_t *gefx;

  gefx = wmem_new0(wmem_packet_scope(), gef_ctx_t);
  gefx->signature = GEF_CTX_SIGNATURE;
  gefx->parent = parent;
  gefx->type = type;
  return gefx;
}
static usb_i1d3_transaction_t *usb_i1d3_create_transaction(
        usb_i1d3_conversation_t *conversation, guint32 request) {
    usb_i1d3_transaction_t *transaction = wmem_new0(
            wmem_file_scope(), usb_i1d3_transaction_t);
    transaction->request = request;
    wmem_map_insert(
            conversation->request_to_transaction,
            GUINT_TO_POINTER(transaction->request), (void *)transaction);
    return transaction;
}
static void set_do_address(asn1_ctx_t* actx, gboolean do_address)
{
    p1_address_ctx_t* ctx;

    if (actx->subtree.tree_ctx == NULL) {
        actx->subtree.tree_ctx = wmem_new0(wmem_packet_scope(), p1_address_ctx_t);
    }

    ctx = (p1_address_ctx_t*)actx->subtree.tree_ctx;
    ctx->do_address = do_address;
}
Exemple #10
0
wmem_tree_t *
wmem_tree_new(wmem_allocator_t *allocator)
{
    wmem_tree_t *tree;

    tree = wmem_new0(allocator, wmem_tree_t);
    tree->master    = allocator;
    tree->allocator = allocator;

    return tree;
}
Exemple #11
0
static ipmi_frame_data_t *
get_frame_data(ipmi_packet_data_t * data, guint32 frame_num)
{
	ipmi_frame_data_t * frame = (ipmi_frame_data_t *)
			wmem_tree_lookup32(data->frame_tree, frame_num);

	if (frame == NULL) {
		frame = wmem_new0(wmem_file_scope(), ipmi_frame_data_t);

		wmem_tree_insert32(data->frame_tree, frame_num, frame);
	}
	return frame;
}
Exemple #12
0
static asn1_par_t *push_new_par(asn1_ctx_t *actx) {
  asn1_par_t *par, **pp;

  DISSECTOR_ASSERT(actx->stack);

  par = wmem_new0(wmem_packet_scope(), asn1_par_t);

  pp = &(actx->stack->par);
  while (*pp)
    pp = &((*pp)->next);
  *pp = par;

  return par;
}
void p1_initialize_content_globals (asn1_ctx_t* actx, proto_tree *tree, gboolean report_unknown_cont_type)
{
    p1_address_ctx_t* ctx;

    if (actx->subtree.tree_ctx == NULL) {
        actx->subtree.tree_ctx = wmem_new0(wmem_packet_scope(), p1_address_ctx_t);
    }

    ctx = (p1_address_ctx_t*)actx->subtree.tree_ctx;

    actx->subtree.top_tree = tree;
    actx->external.direct_reference = NULL;
    ctx->content_type_id = NULL;
    ctx->report_unknown_content_type = report_unknown_cont_type;
}
Exemple #14
0
/* When seeing a broadcast talking about an open TCP port on a host, create
 * a conversation to dissect anything sent/received at that address.  Setup
 * protocol data so the TCP dissection knows what broadcast triggered it. */
static void
prepare_ldss_transfer_conv(ldss_broadcast_t *broadcast)
{
	conversation_t *transfer_conv;
	ldss_transfer_info_t *transfer_info;

	transfer_info = wmem_new0(wmem_file_scope(), ldss_transfer_info_t);
	transfer_info->broadcast = broadcast;

	/* Preparation for later push/pull dissection */
	transfer_conv = conversation_new (broadcast->num, &broadcast->broadcaster->addr, &broadcast->broadcaster->addr,
					  PT_TCP, broadcast->broadcaster->port, broadcast->broadcaster->port, NO_ADDR2|NO_PORT2);
	conversation_add_proto_data(transfer_conv, proto_ldss, transfer_info);
	conversation_set_dissector(transfer_conv, ldss_tcp_handle);
}
Exemple #15
0
static void
match_request_response(ipmi_packet_data_t * data, const ipmi_header_t * hdr,
		guint flags)
{
	/* get current frame */
	ipmi_frame_data_t * rs_frame = data->curr_frame;

	/* get current command data */
	ipmi_cmd_data_t * rs_data = rs_frame->cmd_data[data->curr_level];

	/* check if parse response for the first time */
	if (!rs_data) {
		ipmi_request_t * rq;

		/* allocate command data */
		rs_data = wmem_new0(wmem_file_scope(), ipmi_cmd_data_t);

		/* search for matching request */
		rq = get_matched_request(data, hdr, flags);

		/* check if matching request is found */
		if (rq) {
			/* get request frame data */
			ipmi_frame_data_t * rq_frame =
					get_frame_data(data, rq->frame_num);

			/* get command data */
			ipmi_cmd_data_t * rq_data = rq_frame->cmd_data[rq->nest_level];

			/* save matched frame numbers */
			rq_data->matched_frame_num = data->curr_frame_num;
			rs_data->matched_frame_num = rq->frame_num;

			/* copy saved command data information */
			rs_data->saved_data[0] = rq_data->saved_data[0];
			rs_data->saved_data[1] = rq_data->saved_data[1];

			/* remove request from the list */
			wmem_list_remove(data->request_list, rq);

			/* delete request data */
			wmem_free(wmem_file_scope(), rq);
		}

		/* save command data pointer in frame */
		rs_frame->cmd_data[data->curr_level] = rs_data;
	}
}
static usb_i1d3_conversation_t *usb_i1d3_get_conversation(packet_info *pinfo) {
    conversation_t *conversation = find_or_create_conversation(pinfo);
    usb_i1d3_conversation_t* i1d3_conversation =
        (usb_i1d3_conversation_t *)conversation_get_proto_data(
                conversation, proto_usb_i1d3);
    if (!i1d3_conversation) {
        i1d3_conversation = wmem_new0(
                wmem_file_scope(), usb_i1d3_conversation_t);
        i1d3_conversation->request_to_transaction = wmem_map_new(
                wmem_file_scope(), g_direct_hash, g_direct_equal);
        i1d3_conversation->response_to_transaction = wmem_map_new(
                wmem_file_scope(), g_direct_hash, g_direct_equal);
        conversation_add_proto_data(
                conversation, proto_usb_i1d3, i1d3_conversation);
    }
    return i1d3_conversation;
}
void
register_seq_analysis(const char* name, const char* ui_name, const int proto_id, const char* tap_listener, guint tap_flags, tap_packet_cb tap_func)
{
    register_analysis_t* analysis;

    DISSECTOR_ASSERT(tap_func);

    analysis = wmem_new0(wmem_epan_scope(), register_analysis_t);

    analysis->name          = name;
    analysis->ui_name       = ui_name;
    analysis->proto_id      = proto_id;
    if (tap_listener != NULL)
        analysis->tap_listen_str = tap_listener;
    else
        analysis->tap_listen_str = proto_get_protocol_filter_name(proto_id);
    analysis->tap_flags     = tap_flags;
    analysis->analysis_func = tap_func;

    if (registered_seq_analysis == NULL)
        registered_seq_analysis = wmem_tree_new(wmem_epan_scope());

    wmem_tree_insert_string(registered_seq_analysis, name, analysis, 0);
}
static int
dissect_ppcap_source_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree * ppcap_tree1, int offset)
{
	int key1;
	guint16 msg_len;
	msg_len = tvb_get_ntohs(tvb, offset);
	proto_tree_add_item( ppcap_tree1, hf_ppcap_length, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset  = offset + 2;
	proto_tree_add_item(ppcap_tree1, hf_ppcap_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;

	key1 = tvb_get_ntohs(tvb, offset);
	proto_tree_add_item(ppcap_tree1, hf_ppcap_address_type, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;

	if (key1 == 1)
	{
		proto_tree_add_item(ppcap_tree1, hf_ppcap_ssn, tvb, offset, 1, ENC_BIG_ENDIAN);
		offset += 1;
		proto_tree_add_item(ppcap_tree1, hf_ppcap_spc, tvb, offset, 3, ENC_BIG_ENDIAN);
		/*src_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/
		mtp3_addr_opc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t);
		mtp3_addr_opc->pc = (guint32 )tvb_get_ntoh24(tvb, offset);
		mtp3_addr_opc->type = ITU_STANDARD;
		mtp3_addr_opc->ni = 0;
		/*SET_ADDRESS(&pinfo->net_src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc);*/
		SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc);
		if (msg_len%4)
			msg_len = msg_len + (4 - (msg_len%4));

		offset += msg_len-1;
		return offset;
	}
	else if (key1 == 2)
	{
		proto_tree_add_item(ppcap_tree1, hf_ppcap_opc, tvb, offset, msg_len, ENC_BIG_ENDIAN);

		/*src_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/
		mtp3_addr_opc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t);
		mtp3_addr_opc->pc = tvb_get_ntohl(tvb, offset);
		mtp3_addr_opc->type = ITU_STANDARD;
		mtp3_addr_opc->ni = 0;
		SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc);
	}
	else if (key1 == 3)
	{
		if (msg_len%16 != 0)
		{

			proto_tree_add_ipv4(ppcap_tree1, hf_ppcap_source_ip_address1, tvb, offset, msg_len, tvb_get_ipv4(tvb, offset));
			TVB_SET_ADDRESS(&pinfo->net_src, AT_IPv4, tvb, offset, 4);
			COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src);
		}
		else
		{
			struct e_in6_addr value;
			tvb_get_ipv6(tvb, offset, &value);
			proto_tree_add_ipv6(ppcap_tree1, hf_ppcap_source_ip_address2, tvb, offset, msg_len, &value);
			TVB_SET_ADDRESS(&pinfo->net_src, AT_IPv6, tvb, offset, 6);
			COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src);
		}
	}

	else if (key1 == 4)

	{
		proto_tree_add_item(ppcap_tree1, hf_ppcap_source_nodeid, tvb, offset, msg_len, ENC_ASCII|ENC_NA);
		TVB_SET_ADDRESS(&pinfo->net_src, AT_STRINGZ, tvb, offset, msg_len);
		COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src);
	}
	if (msg_len%4)
		msg_len = msg_len + (4 - (msg_len%4));
	offset += msg_len;
	return offset;
}
Exemple #19
0
/* 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);
	transfer_info = (ldss_transfer_info_t *)conversation_get_proto_data(transfer_conv, proto_ldss);

	/* 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;
		}

		if (tree) {
			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(NULL, 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);
				if (tree) {
					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);
				if (tree) {
					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 */
				if (tree) {
					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) {
				/* 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);
				}
				if (tree) {
					proto_item *tii = NULL;

					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 (tree && 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 0;
			}
		}

		/* 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");

		if (tree) {
			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);
}
Exemple #20
0
/* Broadcasts are searches, offers or promises.
 *
 * Searches are sent by
 * a peer when it needs a file (ie. while applying its policy, when it needs
 * files such as installers to install software.)
 *
 * Each broadcast relates to one file and each file is identified only by its
 * checksum - no file names are ever used. A search times out after 10 seconds
 * (configurable) and the peer will then attempt to act on any offers by
 * downloading (via push or pull - see dissect_ldss_transfer) from those peers.
 *
 * If no offers are received, the search fails and the peer fetches the file
 * from a remote server, generally a HTTP server on the other side of a WAN.
 * The protocol exists to minimize the number of WAN downloads needed.
 *
 * While downloading from WAN the peer sends promises to inform other peers
 * when it will be available for them to download. This prevents multiple peers
 * simultaneously downloading the same file. Promises also inform other peers
 * how much download bandwidth is being used by their download. Other peers use
 * this information and the configured knowledge of the WAN bandwidth to avoid
 * saturating the WAN link, as file downloads are a non-time-critical and
 * non-business-critical network function. LDSS is intended for networks of
 * 5-20 machines connected by slow WAN link. The current implementation of the
 * protocol allows administrator to configure "time windows" when WAN usage is
 * throttled/unthrottled, though this isn't visible in LDSS.
 *
 * Once a WAN download or a LAN transfer (see below above dissect_ldss_transfer)
 * has complete the peer will offer the file to other peers on the LAN so they
 * don't need to download it themselves.
 *
 * Peers also notify when they shut down in case any other peer is waiting for
 * a file. */
static int
dissect_ldss_broadcast(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint16	messageID;
	guint8 digest_type;
	guint8 compression;
	guint32 cookie;
	guint8 *digest;
	guint64	size;
	guint64	offset;
	guint32	targetTime;
	guint16 port;
	guint16	rate;
	guint16 messageDetail = INFERRED_NONE;

	proto_tree	*ti, *ldss_tree;

	const gchar *packet_type, *packet_detail;

	messageID   = tvb_get_ntohs  (tvb,  0);
	digest_type = tvb_get_guint8 (tvb,  2);
	compression = tvb_get_guint8 (tvb,  3);
	cookie      = tvb_get_ntohl  (tvb,  4);
	digest      = (guint8 *)tvb_memdup (NULL, tvb,  8, DIGEST_LEN);
	size	    = tvb_get_ntoh64 (tvb, 40);
	offset	    = tvb_get_ntoh64 (tvb, 48);
	targetTime  = tvb_get_ntohl  (tvb, 56);
	port        = tvb_get_ntohs  (tvb, 64);
	rate	    = tvb_get_ntohs  (tvb, 66);

	packet_type = val_to_str_const(messageID, ldss_message_id_value, "unknown");

	if (messageID == MESSAGE_ID_WILLSEND) {
		if (cookie == 0) {
			/* Shutdown: Dishonor promises from this peer. Current
			 * implementation abuses WillSend for this. */
			messageDetail = INFERRED_PEERSHUTDOWN;
		}
		else if (size == 0 && offset == 0) {
			/* NeedFile search failed - going to WAN */
			messageDetail = INFERRED_WANDOWNLOAD;
		}
		else if (size > 0) {
			/* Size is known (not always the case) */
			if (size == offset) {
				/* File is available for pull on this peer's TCP port */
				messageDetail = INFERRED_OFFER;
			}
			else {
				/* WAN download progress announcement from this peer */
				messageDetail = INFERRED_PROMISE;
			}
		}
	}
	else if (messageID == MESSAGE_ID_NEEDFILE) {
		messageDetail = INFERRED_SEARCH;
	}
	packet_detail = val_to_str_const(messageDetail, ldss_inferred_info, "unknown");

	/* Set the info column */
	col_add_fstr(pinfo->cinfo, COL_INFO, "LDSS Broadcast (%s%s)",
			     packet_type,
			     packet_detail);

	/* If we have a non-null tree (ie we are building the proto_tree
	 * instead of just filling out the columns), then give more detail. */
	if (tree) {
		ti = proto_tree_add_item(tree, proto_ldss,
					 tvb, 0, (tvb_captured_length(tvb) > 72) ? tvb_captured_length(tvb) : 72, ENC_NA);
		ldss_tree = proto_item_add_subtree(ti, ett_ldss_broadcast);

		proto_tree_add_item(ldss_tree, hf_ldss_message_id,
				    tvb, 0, 2, ENC_BIG_ENDIAN);
		ti = proto_tree_add_uint(ldss_tree, hf_ldss_message_detail,
					 tvb, 0, 0, messageDetail);
		PROTO_ITEM_SET_GENERATED(ti);
		proto_tree_add_item(ldss_tree, hf_ldss_digest_type,
				    tvb, 2,	    1,	ENC_BIG_ENDIAN);
		proto_tree_add_item(ldss_tree, hf_ldss_compression,
				    tvb, 3,	    1,	ENC_BIG_ENDIAN);
		proto_tree_add_uint_format_value(ldss_tree, hf_ldss_cookie,
						 tvb, 4,	    4,	FALSE,
						 "0x%x%s",
						 cookie,
						 (cookie == 0)
						 ? " - shutdown (promises from this peer are no longer valid)"
						 : "");
		proto_tree_add_item(ldss_tree, hf_ldss_digest,
				    tvb, 8,	    DIGEST_LEN, ENC_NA);
		proto_tree_add_item(ldss_tree, hf_ldss_size,
				    tvb, 40,    8,	ENC_BIG_ENDIAN);
		proto_tree_add_item(ldss_tree, hf_ldss_offset,
				    tvb, 48,    8,	ENC_BIG_ENDIAN);
		proto_tree_add_uint_format_value(ldss_tree, hf_ldss_target_time,
						 tvb, 56,    4,	FALSE,
						 "%d:%02d:%02d",
						 (int)(targetTime / 3600),
						 (int)((targetTime / 60) % 60),
						 (int)(targetTime % 60));
		proto_tree_add_item(ldss_tree, hf_ldss_reserved_1,
				    tvb, 60,    4,	ENC_BIG_ENDIAN);
		proto_tree_add_uint_format_value(ldss_tree, hf_ldss_port,
						 tvb, 64,    2,	FALSE,
						 "%d%s",
						 port,
						 (messageID == MESSAGE_ID_WILLSEND &&
						  size > 0 &&
						  size == offset)
						 ? " - file can be pulled at this TCP port"
						 : (messageID == MESSAGE_ID_NEEDFILE
						    ? " - file can be pushed to this TCP port"
						    : ""));
		proto_tree_add_uint_format_value(ldss_tree, hf_ldss_rate,
						 tvb, 66,    2,	FALSE,
						 "%ld",
						 (rate > 0)
						 ? (long)floor(exp(rate * G_LN2 / 2048))
						 : 0);
		proto_tree_add_item(ldss_tree, hf_ldss_priority,
				    tvb, 68, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ldss_tree, hf_ldss_property_count,
				    tvb, 70, 2, ENC_BIG_ENDIAN);
		if (tvb_reported_length(tvb) > 72) {
			proto_tree_add_item(ldss_tree, hf_ldss_properties,
					    tvb, 72, tvb_captured_length(tvb) - 72, ENC_NA);
		}
	}

	/* Finally, store the broadcast and register ourselves to dissect
	 * any pushes or pulls that result from this broadcast. All data
	 * is pushed/pulled over TCP using the port from the broadcast
	 * packet's port field.
	 * Track each by a TCP conversation with the remote end wildcarded.
	 * The TCP conv tracks back to a broadcast conv to determine what it
	 * is in response to.
	 *
	 * These steps only need to be done once per packet, so a variable
	 * tracks the highest frame number seen. Handles the case of first frame
	 * being frame zero. */
	if (messageDetail != INFERRED_PEERSHUTDOWN &&
	    (highest_num_seen == 0 ||
	     highest_num_seen < pinfo->num)) {

		ldss_broadcast_t *data;

		/* Populate data from the broadcast */
		data = wmem_new0(wmem_file_scope(), ldss_broadcast_t);
		data->num = pinfo->num;
		data->ts = pinfo->abs_ts;
		data->message_id = messageID;
		data->message_detail = messageDetail;
		data->port = port;
		data->size = size;
		data->offset = offset;
		data->compression = compression;

		data->file = wmem_new0(wmem_file_scope(), ldss_file_t);
		data->file->digest = digest;
		data->file->digest_type = digest_type;

		data->broadcaster = wmem_new0(wmem_file_scope(), ldss_broadcaster_t);
		copy_address(&data->broadcaster->addr, &pinfo->src);
		data->broadcaster->port = port;

		/* Dissect any future pushes/pulls */
		if (port > 0) {
			prepare_ldss_transfer_conv(data);
		}

		/* Record that the frame was processed */
		highest_num_seen = pinfo->num;
	}

	return tvb_captured_length(tvb);
}
Exemple #21
0
static void
dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  gboolean        is_request;
  proto_tree      *imap_tree, *reqresp_tree;
  proto_item      *ti, *hidden_item;
  gint            offset = 0;
  gint            uid_offset = 0;
  gint            folder_offset = 0;
  const guchar    *line;
  const guchar    *uid_line;
  const guchar    *folder_line;
  gint            next_offset;
  int             linelen;
  int             tokenlen;
  int             uid_tokenlen;
  int             folder_tokenlen;
  const guchar    *next_token;
  const guchar    *uid_next_token;
  const guchar    *folder_next_token;
  guchar          *tokenbuf;
  guchar          *command_token;
  int             iter;
  int             commandlen;
  conversation_t *conversation;
  imap_state_t   *session_state;

  conversation = find_or_create_conversation(pinfo);
  session_state = (imap_state_t *)conversation_get_proto_data(conversation, proto_imap);
  if (!session_state) {
    session_state = wmem_new0(wmem_file_scope(), imap_state_t);
    session_state->ssl_requested = FALSE;
    conversation_add_proto_data(conversation, proto_imap, session_state);
  }

  tokenbuf = (guchar *)wmem_alloc0(wmem_packet_scope(), MAX_BUFFER);
  command_token = (guchar *)wmem_alloc0(wmem_packet_scope(), MAX_BUFFER);
  commandlen = 0;
  folder_offset = 0;
  folder_tokenlen = 0;
  folder_line = NULL;
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "IMAP");


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

  /*
   * Put the first line from the buffer into the summary
   * (but leave out the line terminator).
   */
  linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
  line = tvb_get_ptr(tvb, offset, linelen);

  col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "Request" : "Response", format_text(line, linelen));

  {
    ti = proto_tree_add_item(tree, proto_imap, tvb, offset, -1, ENC_NA);
    imap_tree = proto_item_add_subtree(ti, ett_imap);

    hidden_item = proto_tree_add_boolean(imap_tree, hf_imap_isrequest, tvb, 0, 0, is_request);
    PROTO_ITEM_SET_HIDDEN(hidden_item);

    while(tvb_offset_exists(tvb, offset)) {

      /*
       * Find the end of each line
       *
       * Note that "tvb_find_line_end()" will return a value that is
       * not longer than what's in the buffer, so the "tvb_get_ptr()"
       * call won't throw an exception.
       */
      linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
      line = tvb_get_ptr(tvb, offset, linelen);

      /*
       * Put the line into the protocol tree.
       */
      ti = proto_tree_add_item(imap_tree, hf_imap_line, tvb, offset, next_offset - offset, ENC_ASCII|ENC_NA);

      reqresp_tree = proto_item_add_subtree(ti, ett_imap_reqresp);

      /*
       * Check that the line doesn't begin with '*', because that's a continuation line.
       * Otherwise if a tag is present then extract tokens.
       */
      if ( (line) && ((line[0] != '*') || (TRUE == is_request)) ) {
        /*
         * Show each line as tags + requests or replies.
         */

        /*
         * Extract the first token, and, if there is a first
         * token, add it as the request or reply tag.
         */
        tokenlen = get_token_len(line, line + linelen, &next_token);
        if (tokenlen != 0) {
          proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request_tag : hf_imap_response_tag, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);

          offset += (gint) (next_token - line);
          linelen -= (int) (next_token - line);
          line = next_token;
        }

        /*
         * Extract second token, and, if there is a second
         * token, and it's not uid, add it as the request or reply command.
         */
        tokenlen = get_token_len(line, line + linelen, &next_token);
        if (tokenlen != 0) {
          for (iter = 0; iter < tokenlen && iter < MAX_BUFFER-1; iter++) {
            tokenbuf[iter] = g_ascii_tolower(line[iter]);
          }
          if (tree && is_request && strncmp(tokenbuf, "uid", tokenlen) == 0) {
            proto_tree_add_item(reqresp_tree, hf_imap_request_uid, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);
            /*
             * UID is a precursor to a command, if following the tag,
              * so move to next token to grab the actual command.
              */
            uid_offset = offset;
            uid_offset += (gint) (next_token - line);
            uid_line = next_token;
            uid_tokenlen = get_token_len(uid_line, uid_line + (linelen - tokenlen), &uid_next_token);
            if (tokenlen != 0) {
              proto_tree_add_item(reqresp_tree, hf_imap_request_command, tvb, uid_offset, uid_tokenlen, ENC_ASCII|ENC_NA);

              /*
               * Save command string to do specialized processing.
               */
              for (iter = 0; iter < uid_tokenlen && iter < MAX_BUFFER-1; iter++) {
                command_token[iter] = g_ascii_tolower(uid_line[iter]);
              }
              commandlen = uid_tokenlen;

              folder_offset = uid_offset;
              folder_offset += (gint) (uid_next_token - uid_line);
              folder_line = uid_next_token;
              folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen - uid_tokenlen), &folder_next_token);
            }
          } else {
            /*
             * Not a UID request so perform normal parsing.
             */
            proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request_command : hf_imap_response_status, tvb, offset, tokenlen, ENC_ASCII|ENC_NA);

            if (is_request) {
              /*
               * Save command string to do specialized processing.
               */
              for (iter = 0; iter < tokenlen && iter < 256; iter++) {
                command_token[iter] = g_ascii_tolower(line[iter]);
              }
              commandlen = tokenlen;

              folder_offset = offset;
              folder_offset += (gint) (next_token - line);
              folder_line = next_token;
              folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen - 1), &folder_next_token);
            }
          }

          if (tree && commandlen > 0 && (
              strncmp(command_token, "select", commandlen) == 0 ||
              strncmp(command_token, "examine", commandlen) == 0 ||
              strncmp(command_token, "create", commandlen) == 0 ||
              strncmp(command_token, "delete", commandlen) == 0 ||
              strncmp(command_token, "rename", commandlen) == 0 ||
              strncmp(command_token, "subscribe", commandlen) == 0 ||
              strncmp(command_token, "unsubscribe", commandlen) == 0 ||
              strncmp(command_token, "status", commandlen) == 0 ||
              strncmp(command_token, "append", commandlen) == 0 ||
              strncmp(command_token, "search", commandlen) == 0)) {
            /*
             * These commands support folder as an argument,
             * so parse out the folder name.
             */
            if (folder_tokenlen != 0)
              proto_tree_add_item(reqresp_tree, hf_imap_request_folder, tvb, folder_offset, folder_tokenlen, ENC_ASCII|ENC_NA);
          }

          if (tree && is_request && (NULL != folder_line) && strncmp(command_token, "copy", commandlen) == 0) {
            /*
             * Handle the copy command separately since folder
             * is the second argument for this command.
             */
            folder_offset += (gint) (folder_next_token - folder_line);
            folder_line = folder_next_token;
            folder_tokenlen = get_token_len(folder_line, folder_line + (linelen - tokenlen), &folder_next_token);

            if (folder_tokenlen != 0)
              proto_tree_add_item(reqresp_tree, hf_imap_request_folder, tvb, folder_offset, folder_tokenlen, ENC_ASCII|ENC_NA);
          }

          /* If not yet switched to TLS, check for STARTTLS. */
          if (session_state->ssl_requested) {
            if (!is_request && session_state->ssl_requested &&
              strncmp(tokenbuf, "ok", tokenlen) == 0) {
              /* STARTTLS accepted, next reply will be TLS. */
              ssl_starttls_ack(ssl_handle, pinfo, imap_handle);
            }
            session_state->ssl_requested = FALSE;
          }
          if (is_request && commandlen > 0 &&
            strncmp(command_token, "starttls", commandlen) == 0) {
            /* If next response is OK, then TLS should be commenced. */
            session_state->ssl_requested = TRUE;
          }
        }

        /*
         * Add the rest of the line as request or reply data.
         */
        if (linelen != 0) {
          proto_tree_add_item(reqresp_tree, (is_request) ? hf_imap_request : hf_imap_response, tvb, offset, linelen, ENC_ASCII|ENC_NA);
        }

      }

      offset = next_offset; /* Skip over last line and \r\n at the end of it */
    }
  }
}
/* Decode an EXT_FTI extension and fill FEC array */
void fec_decode_ext_fti(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int offset, guint8 encoding_id)
{
    guint64            transfer_length;
    fec_packet_data_t *fec_data;
    guint8             instance_id = 0;
    proto_item        *ti;

    if (encoding_id == 6){
        /* Raptor Q uses 40-bit transfer length */
        transfer_length = tvb_get_ntoh40(tvb, offset+2);
    }
    else {
        /* Decode 48-bit length field */
        transfer_length = tvb_get_ntoh48(tvb, offset+2);
    }

    if (encoding_id >= 128)
    {
        instance_id = (guint8) tvb_get_ntohs(tvb, offset+8);

        /* Decode FEC Instance ID */
        fec_data = wmem_new0(wmem_file_scope(), fec_packet_data_t);
        fec_data->instance_id = instance_id;

        p_add_proto_data(wmem_file_scope(), pinfo, proto_rmt_fec, 0, fec_data);
    }

    if (encoding_id == 6){
        /* Raptor Q uses 40-bit transfer length */
        proto_tree_add_uint64(tree, hf_fti_transfer_length, tvb, offset+2, 5, transfer_length);
    }
    else {
        proto_tree_add_uint64(tree, hf_fti_transfer_length, tvb, offset+2, 6, transfer_length);
        ti = proto_tree_add_item(tree, hf_instance_id, tvb,  offset+8, 2, ENC_BIG_ENDIAN);
        if ((encoding_id < 128) && (encoding_id != 0)) {
            expert_add_info(pinfo, ti, &ei_fec_encoding_id);
        }
    }

    switch (encoding_id)
    {
    case 1:
        proto_tree_add_item(tree, hf_fti_encoding_symbol_length,      tvb, offset+10, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_fti_num_blocks,                  tvb, offset+12, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_fti_num_subblocks,               tvb, offset+14, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_fti_alignment,                   tvb, offset+15, 1, ENC_BIG_ENDIAN);
        break;

    case 6:
        proto_tree_add_item(tree, hf_fti_encoding_symbol_length,      tvb, offset+8,  2, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_fti_num_blocks,                  tvb, offset+10, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_fti_num_subblocks,               tvb, offset+11, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_fti_alignment,                   tvb, offset+13, 1, ENC_BIG_ENDIAN);
        break;

    case 0:
    case 2:
    case 128:
    case 130:
        proto_tree_add_item(tree, hf_fti_encoding_symbol_length,      tvb, offset+10, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_fti_max_source_block_length,     tvb, offset+12, 4, ENC_BIG_ENDIAN);
        break;

    case 129:
        proto_tree_add_item(tree, hf_fti_encoding_symbol_length,      tvb, offset+10, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_fti_max_source_block_length,     tvb, offset+12, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_fti_max_number_encoding_symbols, tvb, offset+14, 2, ENC_BIG_ENDIAN);
        break;

    case 132:
        proto_tree_add_item(tree, hf_fti_encoding_symbol_length,      tvb, offset+10, 2, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_fti_max_source_block_length,     tvb, offset+12, 4, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_fti_max_number_encoding_symbols, tvb, offset+16, 4, ENC_BIG_ENDIAN);
        break;
    }
}
static int
dissect_ppcap_destination_address(tvbuff_t *tvb, packet_info * pinfo, proto_tree * ppcap_tree1, int offset)
{
	int key2;
	guint16 msg_len;
	msg_len = tvb_get_ntohs(tvb, offset);
	proto_tree_add_item( ppcap_tree1, hf_ppcap_length, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset  = offset + 2;
	proto_tree_add_item(ppcap_tree1, hf_ppcap_destreserved, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;

	key2 = tvb_get_ntohs(tvb, offset);
	proto_tree_add_item(ppcap_tree1, hf_ppcap_address_type, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;

	if (key2 == 1)
	{
		ssn = tvb_get_guint8(tvb, offset);
		proto_tree_add_item(ppcap_tree1, hf_ppcap_ssn1, tvb, offset, 1, ENC_BIG_ENDIAN);
		offset += 1;

		proto_tree_add_item(ppcap_tree1, hf_ppcap_spc1, tvb, offset, 3, ENC_BIG_ENDIAN);

		/*dst_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/
		mtp3_addr_dpc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t);
		mtp3_addr_dpc->pc = (guint32)tvb_get_ntoh24(tvb, offset);
		mtp3_addr_dpc->type = ITU_STANDARD;
		mtp3_addr_dpc->ni = 0;
		SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc);

		if (msg_len%4)
			msg_len = msg_len + (4 - (msg_len%4));

		offset += msg_len-1;
		return offset;

	}
	else if (key2 == 2)
	{
		proto_tree_add_item(ppcap_tree1, hf_ppcap_dpc, tvb, offset, 4, ENC_BIG_ENDIAN);

		/*dst_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/
		mtp3_addr_dpc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t);
		mtp3_addr_dpc->pc = tvb_get_ntohl(tvb, offset);
		mtp3_addr_dpc->type = ITU_STANDARD;
		mtp3_addr_dpc->ni = 0;
		SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc);
	}
	else if (key2 == 3)
	{
		if (msg_len%16 != 0)
		{
			proto_tree_add_ipv4(ppcap_tree1, hf_ppcap_destination_ip_address1, tvb, offset, msg_len, tvb_get_ipv4(tvb, offset));
			TVB_SET_ADDRESS(&pinfo->net_dst, AT_IPv4, tvb, offset, 4);
			COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst);
		}
		else
		{
			struct e_in6_addr value;

			tvb_get_ipv6(tvb, offset,&value);
			proto_tree_add_ipv6(ppcap_tree1, hf_ppcap_destination_ip_address2, tvb, offset, msg_len, &value);
			TVB_SET_ADDRESS(&pinfo->net_dst, AT_IPv6, tvb, offset, 6);
			COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst);
		}
	}

	else if (key2 == 4)
	{
		char *string;
		string = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, msg_len, ENC_UTF_8|ENC_NA);
		proto_tree_add_string(ppcap_tree1, hf_ppcap_destination_nodeid, tvb, offset, msg_len, string);
		TVB_SET_ADDRESS(&pinfo->net_dst, AT_STRINGZ, tvb, offset, msg_len);
		COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst);
	}

	if (msg_len%4)
		msg_len = msg_len+(4-(msg_len%4));

	offset += msg_len;

	return offset;
}
Exemple #24
0
/* Code to actually dissect the packets */
static void
dissect_mtp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    mtp3_tap_rec_t* tap_rec = wmem_new0(wmem_packet_scope(), mtp3_tap_rec_t);
    gint heuristic_standard;
    guint8 si;
    mtp3_addr_pc_t* mtp3_addr_dpc;
    mtp3_addr_pc_t* mtp3_addr_opc;

    /* Set up structures needed to add the protocol subtree and manage it */
    proto_item *mtp3_item = NULL, *gen_item;
    proto_tree *mtp3_tree;

    pref_mtp3_standard = mtp3_standard;

    mtp3_item = proto_tree_add_item(tree, proto_mtp3, tvb, 0, 0, ENC_NA);

    si = tvb_get_guint8(tvb, SIO_OFFSET) & SERVICE_INDICATOR_MASK;
    if (mtp3_heuristic_standard) {
	heuristic_standard = heur_mtp3_standard(tvb, pinfo, si);
	if (heuristic_standard == HEURISTIC_FAILED_STANDARD) {
	    gen_item = proto_tree_add_text(tree, tvb, 0, 0, "Could not determine Heuristic using %s", val_to_str_const(mtp3_standard, mtp3_standard_vals, "unknown"));
	} else {
	    gen_item = proto_tree_add_text(tree, tvb, 0, 0, "%s", val_to_str_const(heuristic_standard, mtp3_standard_vals, "unknown"));
	    mtp3_standard = heuristic_standard;

	    /* Register a frame-end routine to ensure mtp3_standard is set
	     * back even if an exception is thrown.
	     */
	    register_frame_end_routine(pinfo, reset_mtp3_standard);
	}
	PROTO_ITEM_SET_GENERATED(gen_item);
    }

    /* Make entries in Protocol column on summary display */
    switch(mtp3_standard) {
    case ITU_STANDARD:
	col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Int. ITU)");
	proto_item_set_len(mtp3_item, ITU_HEADER_LENGTH);
	break;
    case ANSI_STANDARD:
	col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (ANSI)");
	proto_item_set_len(mtp3_item, ANSI_HEADER_LENGTH);
	break;
    case CHINESE_ITU_STANDARD:
	col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Chin. ITU)");
	proto_item_set_len(mtp3_item, ANSI_HEADER_LENGTH);
	break;
    case JAPAN_STANDARD:
	col_set_str(pinfo->cinfo, COL_PROTOCOL, "MTP3 (Japan)");
	proto_item_set_len(mtp3_item, JAPAN_HEADER_LENGTH);
	break;
    };

	/* create display subtree for the protocol */
	mtp3_tree = proto_item_add_subtree(mtp3_item, ett_mtp3);

    mtp3_addr_opc = (mtp3_addr_pc_t *)wmem_alloc0(pinfo->pool, sizeof(mtp3_addr_pc_t));
    mtp3_addr_dpc = (mtp3_addr_pc_t *)wmem_alloc0(pinfo->pool, sizeof(mtp3_addr_pc_t));

    /* Dissect the packet (even if !tree so can call sub-dissectors and update
     * the source and destination address columns) */
    dissect_mtp3_sio(tvb, mtp3_tree, mtp3_addr_opc, mtp3_addr_dpc);
    dissect_mtp3_routing_label(tvb, pinfo, mtp3_tree, mtp3_addr_opc, mtp3_addr_dpc);

    memcpy(&(tap_rec->addr_opc), mtp3_addr_opc, sizeof(mtp3_addr_pc_t));
    memcpy(&(tap_rec->addr_dpc), mtp3_addr_dpc, sizeof(mtp3_addr_pc_t));

    tap_rec->si_code = (tvb_get_guint8(tvb, SIO_OFFSET) & SERVICE_INDICATOR_MASK);
    tap_rec->size = tvb_length(tvb);

    tap_queue_packet(mtp3_tap, pinfo, tap_rec);

    dissect_mtp3_payload(tvb, pinfo, tree);

    mtp3_standard = pref_mtp3_standard;
}
Exemple #25
0
void
decode_udp_ports(tvbuff_t *tvb, int offset, packet_info *pinfo,
                 proto_tree *tree, int uh_sport, int uh_dport, int uh_ulen)
{
  tvbuff_t *next_tvb;
  int low_port, high_port;
  gint len, reported_len;
  udp_p_info_t *udp_p_info = NULL;
  /* Save curr_layer_num as it might be changed by subdissector */
  guint8 curr_layer_num = pinfo->curr_layer_num;
  heur_dtbl_entry_t *hdtbl_entry;

  len = tvb_captured_length_remaining(tvb, offset);
  reported_len = tvb_reported_length_remaining(tvb, offset);
  if (uh_ulen != -1) {
    /* This is the length from the UDP header; the payload should be cut
       off at that length.  (If our caller passed a value here, they
       are assumed to have checked that it's >= 8, and hence >= offset.)

       XXX - what if it's *greater* than the reported length? */
    if ((uh_ulen - offset) < reported_len)
      reported_len = uh_ulen - offset;
    if (len > reported_len)
      len = reported_len;
  }

  next_tvb = tvb_new_subset(tvb, offset, len, reported_len);

  /* If the user has a "Follow UDP Stream" window loading, pass a pointer
   * to the payload tvb through the tap system. */
  if (have_tap_listener(udp_follow_tap))
    tap_queue_packet(udp_follow_tap, pinfo, next_tvb);

  if (pinfo->fd->flags.visited) {
    udp_p_info = (udp_p_info_t*)p_get_proto_data(wmem_file_scope(), pinfo, hfi_udp->id, pinfo->curr_layer_num);
    if (udp_p_info) {
      call_heur_dissector_direct(udp_p_info->heur_dtbl_entry, next_tvb, pinfo, tree, NULL);
      return;
    }
  }

  /* determine if this packet is part of a conversation and call dissector */
/* for the conversation if available */

  if (try_conversation_dissector(&pinfo->dst, &pinfo->src, PT_UDP,
                                 uh_dport, uh_sport, next_tvb, pinfo, tree, NULL)) {
    return;
  }

  if (try_heuristic_first) {
    /* Do lookup with the heuristic subdissector table */
    if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
      if (!udp_p_info) {
        udp_p_info = wmem_new0(wmem_file_scope(), udp_p_info_t);
        udp_p_info->heur_dtbl_entry = hdtbl_entry;
        p_add_proto_data(wmem_file_scope(), pinfo, hfi_udp->id, curr_layer_num, udp_p_info);
      }
      return;
    }
  }

  /* Do lookups with the subdissector table.
     We try the port number with the lower value first, followed by the
     port number with the higher value.  This means that, for packets
     where a dissector is registered for *both* port numbers:

        1) we pick the same dissector for traffic going in both directions;

        2) we prefer the port number that's more likely to be the right
           one (as that prefers well-known ports to reserved ports);

     although there is, of course, no guarantee that any such strategy
     will always pick the right port number.

     XXX - we ignore port numbers of 0, as some dissectors use a port
     number of 0 to disable the port, and as RFC 768 says that the source
     port in UDP datagrams is optional and is 0 if not used. */
  if (uh_sport > uh_dport) {
    low_port  = uh_dport;
    high_port = uh_sport;
  } else {
    low_port  = uh_sport;
    high_port = uh_dport;
  }
  if ((low_port != 0) &&
      dissector_try_uint(udp_dissector_table, low_port, next_tvb, pinfo, tree))
    return;
  if ((high_port != 0) &&
      dissector_try_uint(udp_dissector_table, high_port, next_tvb, pinfo, tree))
    return;

  if (!try_heuristic_first) {
    /* Do lookup with the heuristic subdissector table */
    if (dissector_try_heuristic(heur_subdissector_list, next_tvb, pinfo, tree, &hdtbl_entry, NULL)) {
      if (!udp_p_info) {
        udp_p_info = wmem_new0(wmem_file_scope(), udp_p_info_t);
        udp_p_info->heur_dtbl_entry = hdtbl_entry;
        p_add_proto_data(wmem_file_scope(), pinfo, hfi_udp->id, curr_layer_num, udp_p_info);
      }
      return;
    }
  }

  call_dissector(data_handle,next_tvb, pinfo, tree);
}
Exemple #26
0
gcp_msg_t* gcp_msg(packet_info* pinfo, int o, gboolean keep_persistent_data) {
    gcp_msg_t* m;
    guint32 framenum = (guint32)pinfo->fd->num;
    guint32 offset = (guint32)o;
    address* src = &(pinfo->src);
    address* dst = &(pinfo->dst);
    address* lo_addr;
    address* hi_addr;

    if (keep_persistent_data) {
        wmem_tree_key_t key[3];

        key[0].length = 1;
        key[0].key = &(framenum);
        key[1].length = 1;
        key[1].key = &offset;
        key[2].length = 0;
        key[2].key =NULL;

        if (( m = (gcp_msg_t *)wmem_tree_lookup32_array(msgs,key) )) {
            m->committed = TRUE;
            return m;
        } else {
            m = wmem_new(wmem_file_scope(), gcp_msg_t);
            m->framenum = framenum;
            m->time = pinfo->fd->abs_ts;
            m->trxs = NULL;
            m->committed = FALSE;

            wmem_tree_insert32_array(msgs,key,m);
        }
    } else {
        m = wmem_new0(wmem_packet_scope(), gcp_msg_t);
        m->framenum = framenum;
        m->trxs = NULL;
        m->committed = FALSE;
    }

    if (CMP_ADDRESS(src, dst) < 0)  {
        lo_addr = src;
        hi_addr = dst;
    } else {
        lo_addr = dst;
        hi_addr = src;
    }

    switch(lo_addr->type) {
        case AT_NONE:
            m->lo_addr = 0;
            m->hi_addr = 0;
            break;
        case AT_IPv4:
            memcpy((guint8*)&(m->hi_addr),hi_addr->data,4);
            memcpy((guint8*)&(m->lo_addr),lo_addr->data,4);
            break;
        case AT_SS7PC:
            m->hi_addr = mtp3_pc_hash((const mtp3_addr_pc_t *)hi_addr->data);
            m->lo_addr = mtp3_pc_hash((const mtp3_addr_pc_t *)lo_addr->data);
            break;
        default:
            /* XXX: heuristic and error prone */
            m->hi_addr = g_str_hash(ep_address_to_str(hi_addr));
            m->lo_addr = g_str_hash(ep_address_to_str(lo_addr));
        break;
    }

    return m;
}