/* obtain an (aligned) EGPRS data block with given bit-offset and
 * bit-length from the parent TVB */
static tvbuff_t *get_egprs_data_block(tvbuff_t *tvb, guint offset_bits,
	guint length_bits, packet_info *pinfo)
{
	tvbuff_t *aligned_tvb;
	const guint initial_spare_bits = 6;
	guint8 *aligned_buf;
	guint min_src_length_bytes = (offset_bits + length_bits + 7) / 8;
	guint length_bytes = (initial_spare_bits + length_bits + 7) / 8;

	tvb_ensure_bytes_exist(tvb, 0, min_src_length_bytes);

	aligned_buf = (guint8 *) wmem_alloc(pinfo->pool, length_bytes);

	/* Copy the data out of the tvb to an aligned buffer */
	clone_aligned_buffer_lsbf(
		offset_bits - initial_spare_bits, length_bytes,
		tvb_get_ptr(tvb, 0, min_src_length_bytes),
		aligned_buf);

	/* clear spare bits and move block header bits to the right */
	aligned_buf[0] = aligned_buf[0] >> initial_spare_bits;

	aligned_tvb = tvb_new_child_real_data(tvb, aligned_buf,
		length_bytes, length_bytes);
	add_new_data_source(pinfo, aligned_tvb, "Aligned EGPRS data bits");

	return aligned_tvb;
}
void
isis_dissect_nlpid_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length)
{
	gboolean first;
	proto_item *ti;

	if ( !tree ) return;		/* nothing to do! */

	/*
	 * Throw an exception rather than putting in a
	 * partial address.
	 */
	tvb_ensure_bytes_exist ( tvb, offset, length );

	if (length <= 0) {
		proto_tree_add_text (tree, tvb, offset, length,
			"NLPID(s): --none--");
	} else {
		first = TRUE;
		ti = proto_tree_add_text (tree, tvb, offset, length,
			"NLPID(s): ");
		while (length-- > 0 ) {
			if (!first) {
				proto_item_append_text(ti, ", ");
			}
			proto_item_append_text(ti, "%s (0x%02x)",
				val_to_str(tvb_get_guint8(tvb, offset), nlpid_vals,
				"Unknown"), tvb_get_guint8(tvb, offset));
			offset++;
			first = FALSE;
		}
	}
}
Example #3
0
guint16 crc16_x25_ccitt_tvb(tvbuff_t *tvb, guint len)
{
    const guint8 *buf;

    tvb_ensure_bytes_exist(tvb, 0, len);  /* len == -1 not allowed */
    buf = tvb_get_ptr(tvb, 0, len);

    return crc16_x25_ccitt_seed(buf, len, 0xFFFF);
}
Example #4
0
guint16 crc16_ccitt_tvb_offset_seed(tvbuff_t *tvb, guint offset, guint len, guint16 seed)
{
    const guint8 *buf;

    tvb_ensure_bytes_exist(tvb, offset, len);  /* len == -1 not allowed */
    buf = tvb_get_ptr(tvb, offset, len);

    return crc16_ccitt_seed(buf, len, seed);
}
Example #5
0
guint32
crc32_ccitt_tvb_seed(tvbuff_t *tvb, guint len, guint32 seed)
{
	const guint8* buf;

	tvb_ensure_bytes_exist(tvb, 0, len);  /* len == -1 not allowed */
	buf = tvb_get_ptr(tvb, 0, len);

	return ( crc32_ccitt_seed(buf, len, seed) );
}
Example #6
0
guint32
crc32_ccitt_tvb_offset(tvbuff_t *tvb, guint offset, guint len)
{
	const guint8* buf;

	tvb_ensure_bytes_exist(tvb, offset, len);  /* len == -1 not allowed */
	buf = tvb_get_ptr(tvb, offset, len);

	return ( crc32_ccitt(buf, len) );
}
Example #7
0
guint32 crc32_0x0AA725CF_tvb_offset_seed(tvbuff_t *tvb,
                                            guint offset, guint len, guint32 seed)
{
    const guint8 *buf;

    tvb_ensure_bytes_exist(tvb, offset, len);  /* len == -1 not allowed */
    buf = tvb_get_ptr(tvb, offset, len);

    return crc32_0x0AA725CF_seed(buf, len, seed);
}
Example #8
0
static int
dissect_rx_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset, guint32 seq, guint32 callnumber)
{
	proto_tree *tree;
	proto_item *item;
	guint32 version, tl;
	int old_offset=offset;

	if (check_col(pinfo->cinfo, COL_INFO)) {
		col_add_fstr(pinfo->cinfo, COL_INFO,
			"RESPONSE  "
			"Seq: %lu  "
			"Call: %lu  "
			"Source Port: %s  "
			"Destination Port: %s  ",
			(unsigned long)seq,
			(unsigned long)callnumber,
			get_udp_port(pinfo->srcport),
			get_udp_port(pinfo->destport)
		);
	}

	item = proto_tree_add_item(parent_tree, hf_rx_response, tvb, offset, -1, FALSE);
	tree = proto_item_add_subtree(item, ett_rx_response);

	version = tvb_get_ntohl(tvb, offset);
	proto_tree_add_uint(tree, hf_rx_version, tvb,
		offset, 4, version);
	offset += 4;

	if (version==2) {
		/* skip unused */
		offset += 4;

		/* encrypted : struct */
		offset = dissect_rx_response_encrypted(tvb, tree, offset);

		/* kvno */
		proto_tree_add_item(tree, hf_rx_kvno, tvb, offset, 4, FALSE);
		offset += 4;

		/* ticket_len */
		tl = tvb_get_ntohl(tvb, offset);
		proto_tree_add_uint(tree, hf_rx_ticket_len, tvb,
			offset, 4, tl);
		offset += 4;

		tvb_ensure_bytes_exist(tvb, offset, tl);
		proto_tree_add_item(tree, hf_rx_ticket, tvb, offset, tl, FALSE);
		offset += tl;
	}

	proto_item_set_len(item, offset-old_offset);
	return offset;
}
Example #9
0
guint16 crc16_plain_tvb_offset_seed(tvbuff_t *tvb, guint offset, guint len, guint16 crc)
{
    const guint8 *buf;

    tvb_ensure_bytes_exist(tvb, offset, len);  /* len == -1 not allowed */
    buf = tvb_get_ptr(tvb, offset, len);

    crc = crc16_plain_update(crc, buf, len);

    return crc16_plain_finalize(crc);
}
/*
 * Name: isis_dissect_area_address_clv()
 *
 * Description:
 *	Take an area address CLV and display it pieces.  An area address
 *	CLV is n, x byte hex strings.
 *
 * Input:
 *	tvbuff_t * : tvbuffer for packet data
 *	proto_tree * : protocol display tree to fill out.  May be NULL
 *	int : offset into packet data where we are.
 *	int : length of clv we are decoding
 *
 * Output:
 *	void, but we will add to proto tree if !NULL.
 */
void
isis_dissect_area_address_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
	int length)
{
	int		arealen,area_idx;

	while ( length > 0 ) {
		arealen = tvb_get_guint8(tvb, offset);
		length--;
		if (length<=0) {
			isis_dissect_unknown(tvb, tree, offset,
				"short address (no length for payload)");
			return;
		}
		if ( arealen > length) {
			isis_dissect_unknown(tvb, tree, offset,
				"short address, packet says %d, we have %d left",
				arealen, length );
			return;
		}

		if ( tree ) {
			proto_item *ti;
	
			/*
			 * Throw an exception rather than putting in a
			 * partial address.
			 */
			tvb_ensure_bytes_exist ( tvb, offset, arealen + 1 );

			ti = proto_tree_add_text ( tree, tvb, offset, arealen + 1,
				"Area address (%d): ", arealen );

			/*
			 * Lets turn the area address into "standard"
			 * xx.xxxx.xxxx.xxxx.xxxx.xxxx.xxxx format string.
	                 * this is a private routine as the print_nsap_net in
			 * epan/osi_utils.c is incomplete and we need only
			 * a subset - actually some nice placing of dots ....
			 */
			for (area_idx = 0; area_idx < arealen; area_idx++) {
				proto_item_append_text(ti, "%02x",
				    tvb_get_guint8(tvb, offset+area_idx+1));
				if (((area_idx & 1) == 0) &&
				    (area_idx + 1 < arealen)) {
					proto_item_append_text(ti, ".");
				}
			}
		}
		offset += arealen + 1;
		length -= arealen;	/* length already adjusted for len fld*/
	}
}
static void
dissect_option_rfd( const guchar error, const guchar field, int offset,
                          guchar len, tvbuff_t *tvb, proto_tree *tree ) {
  guchar error_class = 0;
  const char   *format_string[] =
             { "Reason for discard {General}        : %s, in field %u",
               "Reason for discard {Address}        : %s, in field %u",
               "Reason for discard {Source Routing}: %s, in field %u",
               "Reason for discard {Lifetime}       : %s, in field %u",
               "Reason for discard {PDU discarded}  : %s, in field %u",
               "Reason for discard {Reassembly}     : %s, in field %u"
             };

  error_class = error & OSI_OPT_RFD_MASK;
  tvb_ensure_bytes_exist(tvb, offset + field, 1);

  if ( OSI_OPT_RFD_GENERAL == error_class ) {
    proto_tree_add_text( tree, tvb, offset + field, 1, format_string[0],
                         val_to_str( error & OSI_OPT_RFD_SUB_MASK,
                               osi_opt_rfd_general, "Unknown (0x%x)"), field );
  }
  else if ( OSI_OPT_RFD_ADDRESS == error_class ) {
    proto_tree_add_text( tree, tvb, offset + field, 1, format_string[1],
                         val_to_str( error & OSI_OPT_RFD_SUB_MASK,
                               osi_opt_rfd_address, "Unknown (0x%x)"), field );
  }
  else if ( OSI_OPT_RFD_SOURCE_ROUTING == error_class ) {
    proto_tree_add_text( tree, tvb, offset + field, 1, format_string[2],
                         val_to_str( error & OSI_OPT_RFD_SUB_MASK,
                             osi_opt_rfd_src_route, "Unknown (0x%x)"), field );
  }
  else if ( OSI_OPT_RFD_LIFETIME == error_class ) {
    proto_tree_add_text( tree, tvb, offset + field, 1, format_string[3],
                         val_to_str( error & OSI_OPT_RFD_SUB_MASK,
                              osi_opt_rfd_lifetime, "Unknown (0x%x)"), field );
  }
  else if ( OSI_OPT_RFD_PDU_DISCARDED == error_class ) {
    proto_tree_add_text( tree, tvb, offset + field, 1, format_string[4],
                         val_to_str( error & OSI_OPT_RFD_SUB_MASK,
                             osi_opt_rfd_discarded, "Unknown (0x%x)"), field );
  }
  else if ( OSI_OPT_RFD_REASSEMBLY == error_class ) {
    proto_tree_add_text( tree, tvb, offset + field, 1, format_string[5],
                         val_to_str( error & OSI_OPT_RFD_SUB_MASK,
                            osi_opt_rfd_reassembly, "Unknown (0x%x)"), field );
  }
  else {
    proto_tree_add_text( tree, tvb, offset, len,
                         "Reason for discard: UNKNOWN Error Class" );
  }
}
Example #12
0
static void dissect_noop(tvbuff_t* tvb, proto_tree* lwres_tree)
{
    guint16 datalen;

    proto_tree* noop_tree;

    datalen = tvb_get_ntohs(tvb, LWRES_LWPACKET_LENGTH);

    if(lwres_tree == NULL)
        return;

    noop_tree = proto_tree_add_subtree(lwres_tree, tvb, LWRES_LWPACKET_LENGTH, 10, ett_noop, NULL, "Noop record");

    proto_tree_add_uint(noop_tree, hf_length, tvb,
                LWRES_LWPACKET_LENGTH, sizeof(guint16), datalen);

    tvb_ensure_bytes_exist(tvb, LWRES_LWPACKET_LENGTH, datalen);

}
Example #13
0
void
isis_dissect_nlpid_clv(tvbuff_t *tvb, proto_tree *tree, int offset, int length)
{
    gboolean first;
    proto_item *ti;

    if ( !tree ) return;        /* nothing to do! */

    /*
     * Throw an exception rather than putting in a
     * partial address.
     */
    tvb_ensure_bytes_exist ( tvb, offset, length );

    if (length <= 0) {
        proto_tree_add_text (tree, tvb, offset, length,
            "NLPID(s): --none--");
    } else {
        first = TRUE;
        ti = proto_tree_add_text (tree, tvb, offset, length,
            "NLPID(s): ");
        while (length-- > 0 ) {
            if (!first) {
                proto_item_append_text(ti, ", ");
            }
            proto_item_append_text(ti, "%s (0x%02x)",
                           /* NLPID_IEEE_8021AQ conflicts with NLPID_SNDCF.
                        * In this context, we want the former.
                        */
                           (tvb_get_guint8(tvb, offset) == NLPID_IEEE_8021AQ
                        ? "IEEE 802.1aq (SPB)"
                        : val_to_str_const(tvb_get_guint8(tvb, offset), nlpid_vals, "Unknown")),
                           tvb_get_guint8(tvb, offset));
            offset++;
            first = FALSE;
        }
    }
}
Example #14
0
static int
dissect_rtspmessage(tvbuff_t *tvb, int offset, packet_info *pinfo,
	proto_tree *tree)
{
	proto_tree		*rtsp_tree = NULL;
	proto_tree		*sub_tree = NULL;
	proto_item		*ti = NULL;
	const guchar		*line;
	gint			next_offset;
	const guchar		*linep, *lineend;
	int			orig_offset;
	int			first_linelen, linelen;
	int			line_end_offset;
	int			colon_offset;
	gboolean		is_request_or_reply;
	gboolean		body_requires_content_len;
	gboolean		saw_req_resp_or_header;
	guchar			c;
	rtsp_type_t		rtsp_type;
	gboolean		is_header;
	int			datalen;
	int			content_length;
	int			reported_datalen;
	int			value_offset;
	int			value_len;
	e164_info_t		e164_info;
	gint			rdt_feature_level = 0;
	gchar			*media_type_str_lower_case = NULL;
	int			semi_colon_offset;
	int			par_end_offset;

	/*
	 * Is this a request or response?
	 *
	 * 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.
	 */
	first_linelen = tvb_find_line_end(tvb, offset,
	    tvb_ensure_length_remaining(tvb, offset), &next_offset,
	    FALSE);

	/*
	 * Is the first line a request or response?
	 */
	line = tvb_get_ptr(tvb, offset, first_linelen);
	is_request_or_reply = is_rtsp_request_or_reply(line, first_linelen,
	    &rtsp_type);
	if (is_request_or_reply) {
                /*
		 * Yes, it's a request or response.
		 * Do header desegmentation if we've been told to,
		 * and do body desegmentation if we've been told to and
		 * we find a Content-Length header.
		 */
		if (!req_resp_hdrs_do_reassembly(tvb, offset, pinfo,
		    rtsp_desegment_headers, rtsp_desegment_body)) {
			/*
			 * More data needed for desegmentation.
			 */
			return -1;
		}
	}

	/*
	 * RFC 2326 says that a content length must be specified
	 * in requests that have a body, although section 4.4 speaks
	 * of a server closing the connection indicating the end of
	 * a reply body.
	 *
	 * We assume that an absent content length in a request means
	 * that we don't have a body, and that an absent content length
	 * in a reply means that the reply body runs to the end of
	 * the connection.  If the first line is neither, we assume
	 * that whatever follows a blank line should be treated as a
	 * body; there's not much else we can do, as we're jumping
	 * into the message in the middle.
	 *
	 * XXX - if there was no Content-Length entity header, we should
	 * accumulate all data until the end of the connection.
	 * That'd require that the TCP dissector call subdissectors
	 * for all frames with FIN, even if they contain no data,
	 * which would require subdissectors to deal intelligently
	 * with empty segments.
	 */
	if (rtsp_type == RTSP_REQUEST)
		body_requires_content_len = TRUE;
	else
		body_requires_content_len = FALSE;

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTSP");
	if (check_col(pinfo->cinfo, COL_INFO)) {
		/*
		 * Put the first line from the buffer into the summary
 		 * if it's an RTSP request or reply (but leave out the
		 * line terminator).
		 * Otherwise, just call it a continuation.
		 *
		 * 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.
		 */
		line = tvb_get_ptr(tvb, offset, first_linelen);
		if (is_request_or_reply)
			if ( rtsp_type == RTSP_REPLY ) {
				col_set_str(pinfo->cinfo, COL_INFO, "Reply: ");
				col_append_str(pinfo->cinfo, COL_INFO,
					format_text(line, first_linelen));
			}
			else
				col_add_str(pinfo->cinfo, COL_INFO,
					format_text(line, first_linelen));

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

	}

	orig_offset = offset;
	if (tree) {
		ti = proto_tree_add_item(tree, proto_rtsp, tvb, offset,	-1,
		    FALSE);
		rtsp_tree = proto_item_add_subtree(ti, ett_rtsp);
	}

	/*
	 * We haven't yet seen a Content-Length header.
	 */
	content_length = -1;

	/*
	 * Process the packet data, a line at a time.
	 */
	saw_req_resp_or_header = FALSE;	/* haven't seen anything yet */
	while (tvb_reported_length_remaining(tvb, offset) != 0) {
		/*
		 * We haven't yet concluded that this is a header.
		 */
		is_header = FALSE;

		/*
		 * Find the end of the line.
		 */
		linelen = tvb_find_line_end(tvb, offset,
		    tvb_ensure_length_remaining(tvb, offset), &next_offset,
		    FALSE);
		if (linelen < 0)
			return -1;
		line_end_offset = offset + linelen;
		/*
		 * colon_offset may be -1
		 */
		colon_offset = tvb_find_guint8(tvb, offset, linelen, ':');


		/*
		 * Get a buffer that refers to the line.
		 */
		line = tvb_get_ptr(tvb, offset, linelen);
		lineend = line + linelen;

		/*
		 * OK, does it look like an RTSP request or response?
		 */
		is_request_or_reply = is_rtsp_request_or_reply(line, linelen, &rtsp_type);
		if (is_request_or_reply)
			goto is_rtsp;

		/*
		 * No.  Does it look like a blank line (as would appear
		 * at the end of an RTSP request)?
		 */
		if (linelen == 0)
			goto is_rtsp;	/* Yes. */

		/*
		 * No.  Does it look like a header?
		 */
		linep = line;
		while (linep < lineend) {
			c = *linep++;

			/*
			 * This must be a CHAR to be part of a token; that
			 * means it must be ASCII.
			 */
			if (!isascii(c))
				break;	/* not ASCII, thus not a CHAR */

			/*
			 * This mustn't be a CTL to be part of a token.
			 *
			 * XXX - what about leading LWS on continuation
			 * lines of a header?
			 */
			if (iscntrl(c))
				break;	/* CTL, not part of a header */

			switch (c) {

			case '(':
			case ')':
			case '<':
			case '>':
			case '@':
			case ',':
			case ';':
			case '\\':
			case '"':
			case '/':
			case '[':
			case ']':
			case '?':
			case '=':
			case '{':
			case '}':
				/*
				 * It's a tspecial, so it's not
				 * part of a token, so it's not
				 * a field name for the beginning
				 * of a header.
				 */
				goto not_rtsp;

			case ':':
				/*
				 * This ends the token; we consider
				 * this to be a header.
				 */
				is_header = TRUE;
				goto is_rtsp;

			case ' ':
			case '\t':
				/*
				 * LWS (RFC-2616, 4.2); continue the previous
				 * header.
				 */
				goto is_rtsp;
			}
		}

		/*
		 * We haven't seen the colon, but everything else looks
		 * OK for a header line.
		 *
		 * If we've already seen an RTSP request or response
		 * line, or a header line, and we're at the end of
		 * the tvbuff, we assume this is an incomplete header
		 * line.  (We quit this loop after seeing a blank line,
		 * so if we've seen a request or response line, or a
		 * header line, this is probably more of the request
		 * or response we're presumably seeing.  There is some
		 * risk of false positives, but the same applies for
		 * full request or response lines or header lines,
		 * although that's less likely.)
		 *
		 * We throw an exception in that case, by checking for
		 * the existence of the next byte after the last one
		 * in the line.  If it exists, "tvb_ensure_bytes_exist()"
		 * throws no exception, and we fall through to the
		 * "not RTSP" case.  If it doesn't exist,
		 * "tvb_ensure_bytes_exist()" will throw the appropriate
		 * exception.
		 */
		if (saw_req_resp_or_header)
			tvb_ensure_bytes_exist(tvb, offset, linelen + 1);

	not_rtsp:
		/*
		 * We don't consider this part of an RTSP request or
		 * reply, so we don't display it.
		 */
		break;

	is_rtsp:
		/*
		 * Process this line.
		 */
		if (linelen == 0) {
			/*
			 * This is a blank line, which means that
			 * whatever follows it isn't part of this
			 * request or reply.
			 */
			proto_tree_add_text(rtsp_tree, tvb, offset,
			                    next_offset - offset, "%s",
			                    tvb_format_text(tvb, offset, next_offset - offset));
			offset = next_offset;
			break;
		}

		/*
		 * Not a blank line - either a request, a reply, or a header
		 * line.
		 */
		saw_req_resp_or_header = TRUE;
		if (rtsp_tree) {

			switch (rtsp_type)
			{
				case RTSP_REQUEST:
					process_rtsp_request(tvb, offset, line, linelen, next_offset, rtsp_tree);
					break;
	
				case RTSP_REPLY:
					process_rtsp_reply(tvb, offset, line, linelen, next_offset, rtsp_tree);
					break;
	
				case RTSP_NOT_FIRST_LINE:
					/* Drop through, it may well be a header line */
					break;
			}
		}

		if (is_header)
		{
			/* We know that colon_offset must be set */
			
			/* Skip whitespace after the colon. */
			value_offset = colon_offset + 1;
			while ((value_offset < line_end_offset) &&
				   ((c = tvb_get_guint8(tvb, value_offset)) == ' ' || c == '\t'))
			{
				value_offset++;
			}
			value_len = line_end_offset - value_offset;

			/*
			 * Process some headers specially.
			 */
#define HDR_MATCHES(header) \
	( (size_t)linelen > STRLEN_CONST(header) && \
	 g_ascii_strncasecmp(line, (header), STRLEN_CONST(header)) == 0)

			if (HDR_MATCHES(rtsp_transport))
			{
				proto_tree_add_string(rtsp_tree, hf_rtsp_transport, tvb,
				                      offset, linelen,
				                      tvb_format_text(tvb, value_offset,
				                                      value_len));

				/*
				 * Based on the port numbers specified
				 * in the Transport: header, set up
				 * a conversation that will be dissected
				 * with the appropriate dissector.
				 */
				rtsp_create_conversation(pinfo, line, linelen, rdt_feature_level);
			} else if (HDR_MATCHES(rtsp_content_type))
			{
				proto_tree_add_string(rtsp_tree, hf_rtsp_content_type,
				                      tvb, offset, linelen,
				                      tvb_format_text(tvb, value_offset,
				                                      value_len));

				offset = offset + STRLEN_CONST(rtsp_content_type);
				/* Skip wsp */
				offset = tvb_skip_wsp(tvb, offset, value_len);
				semi_colon_offset = tvb_find_guint8(tvb, value_offset, value_len, ';');
				if ( semi_colon_offset != -1) {
					/* m-parameter present */
					par_end_offset = tvb_skip_wsp_return(tvb, semi_colon_offset-1);
					value_len = par_end_offset - offset;
				}

				media_type_str_lower_case = ascii_strdown_inplace(
                                    (gchar *)tvb_get_ephemeral_string(tvb, offset, value_len));

			} else if (HDR_MATCHES(rtsp_content_length))
			{
				proto_tree_add_uint(rtsp_tree, hf_rtsp_content_length,
				                    tvb, offset, linelen,
				                    atoi(tvb_format_text(tvb, value_offset,
				                                         value_len)));

				/*
				 * Only the amount specified by the
				 * Content-Length: header should be treated
				 * as payload.
				 */
				content_length = rtsp_get_content_length(line, linelen);

			} else if (HDR_MATCHES(rtsp_Session))
			{
				/* Put the value into the protocol tree */
				proto_tree_add_string(rtsp_tree, hf_rtsp_session, tvb,
				                      offset, linelen,
				                      tvb_format_text(tvb, value_offset, value_len));

			} else if (HDR_MATCHES(rtsp_X_Vig_Msisdn)) {
				/*
				 * Extract the X_Vig_Msisdn string
				 */
				if (colon_offset != -1)
				{
					/* Put the value into the protocol tree */
					ti = proto_tree_add_string(rtsp_tree, hf_rtsp_X_Vig_Msisdn,tvb,
					                           offset, linelen ,
					                           tvb_format_text(tvb, value_offset, value_len));
					sub_tree = proto_item_add_subtree(ti, ett_rtsp_method);

					e164_info.e164_number_type = CALLING_PARTY_NUMBER;
					e164_info.nature_of_address = 0;

					e164_info.E164_number_str = tvb_get_ephemeral_string(tvb, value_offset,
					                                              value_len);
					e164_info.E164_number_length = value_len;
					dissect_e164_number(tvb, sub_tree, value_offset,
					                    value_len, e164_info);
				}
			} else if (HDR_MATCHES(rtsp_rdt_feature_level))
			{
				rdt_feature_level = atoi(tvb_format_text(tvb, value_offset,
				                                         value_len));
				proto_tree_add_uint(rtsp_tree, hf_rtsp_rdtfeaturelevel,
				                    tvb, offset, linelen,
				                    atoi(tvb_format_text(tvb, value_offset,
				                                         value_len)));
			}
			else
			{
				/* Default case for headers. Show line as text */
				proto_tree_add_text(rtsp_tree, tvb, offset,
				                    next_offset - offset, "%s",
				                    tvb_format_text(tvb, offset, next_offset - offset));
			}
		}
		else if (rtsp_type == RTSP_NOT_FIRST_LINE)
		{
			/* Catch-all for all other lines... Show line as text.
			   TODO: should these be shown as errors? */
			proto_tree_add_text(rtsp_tree, tvb, offset,
			                    next_offset - offset, "%s",
			                    tvb_format_text(tvb, offset, next_offset - offset));
		}
		
		offset = next_offset;
	}

	/*
	 * Have now read all of the lines of this message.
	 *
	 * If a content length was supplied, the amount of data to be
	 * processed as RTSP payload is the minimum of the content
	 * length and the amount of data remaining in the frame.
	 *
	 * If no content length was supplied (or if a bad content length
	 * was supplied), the amount of data to be processed is the amount
	 * of data remaining in the frame.
	 */
	datalen = tvb_length_remaining(tvb, offset);
	reported_datalen = tvb_reported_length_remaining(tvb, offset);
	if (content_length != -1) {
		/*
		 * Content length specified; display only that amount
		 * as payload.
		 */
		if (datalen > content_length)
			datalen = content_length;

		/*
		 * XXX - limit the reported length in the tvbuff we'll
		 * hand to a subdissector to be no greater than the
		 * content length.
		 *
		 * We really need both unreassembled and "how long it'd
		 * be if it were reassembled" lengths for tvbuffs, so
		 * that we throw the appropriate exceptions for
		 * "not enough data captured" (running past the length),
		 * "packet needed reassembly" (within the length but
		 * running past the unreassembled length), and
		 * "packet is malformed" (running past the reassembled
		 * length).
		 */
		if (reported_datalen > content_length)
			reported_datalen = content_length;
	} else {
		/*
		 * No content length specified; if this message doesn't
		 * have a body if no content length is specified, process
		 * nothing as payload.
		 */
		if (body_requires_content_len)
			datalen = 0;
	}

	if (datalen > 0) {
		/*
		 * There's stuff left over; process it.
		 */
		tvbuff_t *new_tvb;

		/*
		 * Now create a tvbuff for the Content-type stuff and
		 * dissect it.
		 *
		 * The amount of data to be processed that's
		 * available in the tvbuff is "datalen", which
		 * is the minimum of the amount of data left in
		 * the tvbuff and any specified content length.
		 *
		 * The amount of data to be processed that's in
		 * this frame, regardless of whether it was
		 * captured or not, is "reported_datalen",
		 * which, if no content length was specified,
		 * is -1, i.e. "to the end of the frame.
		 */
		new_tvb = tvb_new_subset(tvb, offset, datalen,
			    reported_datalen);

		if (media_type_str_lower_case && 
			dissector_try_string(media_type_dissector_table,
				media_type_str_lower_case,
				new_tvb, pinfo, rtsp_tree)){
			
		}else {
			/*
			 * Fix up the top-level item so that it doesn't
			 * include the SDP stuff.
			 */
			if (ti != NULL)
				proto_item_set_len(ti, offset);

			if (tvb_get_guint8(tvb, offset) == RTSP_FRAMEHDR) {
				/*
				 * This is interleaved stuff; don't
				 * treat it as raw data - set "datalen"
				 * to 0, so we won't skip the offset
				 * past it, which will cause our
				 * caller to process that stuff itself.
				 */
				datalen = 0;
			} else {
				proto_tree_add_text(rtsp_tree, tvb, offset,
				    datalen, "Data (%d bytes)",
				    reported_datalen);
			}
		}

		/*
		 * We've processed "datalen" bytes worth of data
		 * (which may be no data at all); advance the
		 * offset past whatever data we've processed.
		 */
		offset += datalen;
	}
	return offset - orig_offset;
}
Example #15
0
/*
 * Add an Ethernet trailer - which, for some captures, might be the FCS
 * rather than a pad-to-60-bytes trailer.
 *
 * If fcs_len is 0, we assume the frame has no FCS; if it's 4, we assume
 * it has an FCS; if it's anything else (such as -1, which means "maybe
 * it does, maybe it doesn't"), we try to infer whether it has an FCS.
 */
void
add_ethernet_trailer(packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
    int trailer_id, tvbuff_t *tvb, tvbuff_t *trailer_tvb, int fcs_len)
{
  /* If there're some bytes left over, it could be a combination of:
     - padding to meet the minimum 64 byte frame length
     - an FCS, if present (if fcs_len is 0, we know it's not present;
       if fcs_len is 4, we know it's present; if fcs_len is -1, we
       need some heuristics to determine whether it's present)
     - information inserted by TAPs or other network monitoring equipment.
    
     If we don't know whether the FCS is present, then, if we don't have a
     network monitoring trailer, and if the Ethernet frame was claimed to
     have had 64 or more bytes - i.e., it was at least an FCS worth of data
     longer than the minimum payload size - we could assume the last 4 bytes
     of the trailer are an FCS. */
  proto_item *item;
  proto_tree *checksum_tree;

  if (trailer_tvb) {
    guint trailer_length, trailer_reported_length;
    guint padding_length = 0;
    gboolean has_fcs = FALSE;
    tvbuff_t *real_trailer_tvb;

    trailer_length = tvb_length(trailer_tvb);
    trailer_reported_length = tvb_reported_length(trailer_tvb);

    /* There can not have been padding when the length of the frame (including the 
       trailer) is less than 60 bytes. */
    if (eth_assume_padding && pinfo->fd->pkt_len>=60) {
        /* Calculate the amount of padding needed for a minimum sized frame */
        if ( (pinfo->fd->pkt_len - trailer_reported_length) < 60 )
            padding_length = 60 - (pinfo->fd->pkt_len - trailer_reported_length);

        /* Add the padding to the tree, unless it should be treated as 
           part of the trailer and therefor be handed over to (one of) 
           the ethernet-trailer dissectors */
        if (padding_length > 0) {
            tvb_ensure_bytes_exist(tvb, 0, padding_length);
            proto_tree_add_item(fh_tree, hf_eth_padding, trailer_tvb, 0,
                padding_length, ENC_NA);
            trailer_length -= padding_length;
            trailer_reported_length -= padding_length;
        }
    }

    if (fcs_len != 0) {
      /* If fcs_len is 4, we assume we definitely have an FCS.
         Otherwise, then, if the frame is big enough that, if we
         have a trailer, it probably inclues an FCS, and we have
         enough space in the trailer for the FCS, we assume we
         have an FCS.

         "Big enough" means 64 bytes or more; any frame that big
         needs no trailer, as there's no need to pad an Ethernet
         packet past 60 bytes.

         The trailer must be at least 4 bytes long to have enough
         space for an FCS. */

      if (fcs_len == 4 || (tvb_reported_length(tvb) >= 64 &&
        trailer_reported_length >= 4)) {
        /* Either we know we have an FCS, or we believe we have an FCS. */
        if (trailer_length < trailer_reported_length) {
          /* The packet is claimed to have enough data for a 4-byte FCS,
             but we didn't capture all of the packet.
             Slice off the 4-byte FCS from the reported length, and
             trim the captured length so it's no more than the reported
             length; that will slice off what of the FCS, if any, is
             in the captured packet. */
          trailer_reported_length -= 4;
          if (trailer_length > trailer_reported_length)
            trailer_length = trailer_reported_length;
          has_fcs = TRUE;
        } else {
          /* We captured all of the packet, including what appears to
             be a 4-byte FCS.  Slice it off. */
          trailer_length -= 4;
          trailer_reported_length -= 4;
          has_fcs = TRUE;
        }
      }
    }

    /* Create a new tvb without the padding and/or the (assumed) fcs */
    if (fcs_len==4) 
      real_trailer_tvb = tvb_new_subset(trailer_tvb, padding_length,
                                trailer_length, trailer_reported_length);
    else
      real_trailer_tvb = tvb_new_subset_remaining(trailer_tvb, padding_length);

    /* Call all ethernet trailer dissectors to dissect the trailer if
       we actually have a trailer.  */
    if (tvb_reported_length(real_trailer_tvb) != 0) {
      if (dissector_try_heuristic(eth_trailer_subdissector_list, 
                                   real_trailer_tvb, pinfo, tree, NULL) ) {
        /* If we're not sure that there is a FCS, all trailer data
           has been given to the ethernet-trailer dissector, so 
           stop dissecting here */
        if (fcs_len!=4) 
            return;
      } else {
        /* No luck with the trailer dissectors, so just display the
           extra bytes as general trailer */
        if (trailer_length != 0) {
          tvb_ensure_bytes_exist(tvb, 0, trailer_length);
          proto_tree_add_item(fh_tree, trailer_id, real_trailer_tvb, 0,
            trailer_length, ENC_NA);
        }
      }
    }

    if (has_fcs) {
      guint32 sent_fcs = tvb_get_ntohl(trailer_tvb, padding_length+trailer_length);
      if(eth_check_fcs){
        guint32 fcs = crc32_802_tvb(tvb, tvb_length(tvb) - 4);
        if (fcs == sent_fcs) {
          item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb,
                                            padding_length+trailer_length, 4, sent_fcs,
                                            "Frame check sequence: 0x%08x [correct]", sent_fcs);
          checksum_tree = proto_item_add_subtree(item, ett_eth_fcs);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb,
                                        padding_length+trailer_length, 4, TRUE);
          PROTO_ITEM_SET_GENERATED(item);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb,
                                        padding_length+trailer_length, 4, FALSE);
          PROTO_ITEM_SET_GENERATED(item);
        } else {
          item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb,
                                            padding_length+trailer_length, 4, sent_fcs,
                                            "Frame check sequence: 0x%08x [incorrect, should be 0x%08x]",
                                            sent_fcs, fcs);
          checksum_tree = proto_item_add_subtree(item, ett_eth_fcs);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb,
                                        padding_length+trailer_length, 4, FALSE);
          PROTO_ITEM_SET_GENERATED(item);
          item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb,
                                        padding_length+trailer_length, 4, TRUE);
          PROTO_ITEM_SET_GENERATED(item);
          expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");
          col_append_str(pinfo->cinfo, COL_INFO, " [ETHERNET FRAME CHECK SEQUENCE INCORRECT]");
        }
      }else{
        item = proto_tree_add_uint_format(fh_tree, hf_eth_fcs, trailer_tvb,
                                          padding_length+trailer_length, 4, sent_fcs,
                                          "Frame check sequence: 0x%08x [validiation disabled]", sent_fcs);
        checksum_tree = proto_item_add_subtree(item, ett_eth_fcs);
        item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_good, trailer_tvb,
                                      padding_length+trailer_length, 4, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
        item = proto_tree_add_boolean(checksum_tree, hf_eth_fcs_bad, trailer_tvb,
                                      padding_length+trailer_length, 4, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
      }
      trailer_length += 4;
    }
    proto_tree_set_appendix(fh_tree, tvb, tvb_length(tvb) - padding_length - trailer_length, padding_length + trailer_length);
  }
}
Example #16
0
/* Function to dissect EDP portion of ISMP message */
static void
dissect_ismp_edp(tvbuff_t *tvb, packet_info *pinfo, int offset, proto_tree *ismp_tree)
{
	/* local variables used for EDP dissection */ 
	int neighbors_count = 0;
	int tuples_count = 0;
	guint16 device_type = 0; 
	guint32	options = 0;
	guint16 num_neighbors = 0;
	guint16 num_tuples = 0;
	guint16 tuple_type = 0;
	guint16 tuple_length = 0;
	const guint8 *neighbors_ptr;
	const guint8 *tuples_ptr;

	/* Set up structures needed to add the protocol subtree and manage it */
	proto_item *edp_ti;
	proto_tree *edp_tree;
	
	proto_item *edp_options_ti;
	proto_tree *edp_options_tree;

	proto_item *edp_neighbors_ti;
	proto_tree *edp_neighbors_tree;

	proto_item *edp_neighbors_leaf_ti;
	proto_tree *edp_neighbors_leaf_tree;

	proto_item *edp_tuples_ti;
	proto_tree *edp_tuples_tree;

	proto_item *edp_tuples_leaf_ti;
	proto_tree *edp_tuples_leaf_tree;

	/* add column iformation marking this as EDP (Enterasys Discover Protocol */
	col_set_str(pinfo->cinfo, COL_PROTOCOL, "ISMP.EDP");
	col_clear(pinfo->cinfo, COL_INFO);

	/* create display subtree for EDP */
	if (ismp_tree) {
		edp_ti  = proto_tree_add_item(ismp_tree, hf_ismp_edp, tvb, offset,
			tvb_length_remaining(tvb, offset), FALSE);
		edp_tree = proto_item_add_subtree(edp_ti, ett_ismp_edp);

		col_add_fstr(pinfo->cinfo, COL_INFO, "MIP %s, MMAC %s, ifIdx %d",
			ip_to_str(tvb_get_ptr(tvb, offset+2, 4)),
			ether_to_str(tvb_get_ptr(tvb, offset+6, 6)),
			tvb_get_ntohl(tvb, offset+12));

		proto_tree_add_item(edp_tree, hf_ismp_edp_version, tvb, offset, 2, FALSE);
		offset += 2;
		proto_tree_add_item(edp_tree, hf_ismp_edp_module_ip, tvb, offset, 4, FALSE);
		offset += 4;
		proto_tree_add_item(edp_tree, hf_ismp_edp_module_mac, tvb, offset, 6, FALSE);
		offset += 6;
		proto_tree_add_item(edp_tree, hf_ismp_edp_module_port, tvb, offset, 4, FALSE);
		offset += 4;
		proto_tree_add_item(edp_tree, hf_ismp_edp_chassis_mac, tvb, offset, 6, FALSE);
		offset += 6;
		proto_tree_add_item(edp_tree, hf_ismp_edp_chassis_ip, tvb, offset, 4, FALSE);
		offset += 4;
		device_type = tvb_get_ntohs(tvb, offset);
		proto_tree_add_item(edp_tree, hf_ismp_edp_device_type, tvb, offset, 2, FALSE);
		offset += 2;
		proto_tree_add_uint_format(edp_tree, hf_ismp_edp_module_rev, tvb, offset, 4, tvb_get_ntohl(tvb, offset),
			"Module Firmware Revision: %02x.%02x.%02x.%02x", tvb_get_guint8(tvb, offset),
			tvb_get_guint8(tvb, offset+1), tvb_get_guint8(tvb, offset+2), tvb_get_guint8(tvb, offset+3));
		offset += 4;

		/* create display subtree for EDP options */
		options = tvb_get_ntohl(tvb, offset);
		edp_options_ti = proto_tree_add_uint_format(edp_tree, hf_ismp_edp_options, tvb, offset, 4,
			options,"Options: 0x%08x",options);
		edp_options_tree = proto_item_add_subtree(edp_options_ti, ett_ismp_edp_options);

		/* depending on device_type, show the appropriate options */
		switch (device_type) {
			case EDP_DEVICE_TYPE_SFS17:
			case EDP_DEVICE_TYPE_SFS18:
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_flood, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_port, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_core, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_uplink_switch, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_isolated, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_redun, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_conmsg, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_calltap, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_tagflood, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_unused2, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_resolve, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_flood, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_lsp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_sfssup, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_sfs_option_unused1, tvb, offset, 4, FALSE);
				break;
			case EDP_DEVICE_TYPE_ROUTER:
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_level1, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_trans, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_route, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_igmp_snoop, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_gmrp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_gvrp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_8021q, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_dvmrp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_ospf, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_bgp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_rip, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_igmp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_rtr_option_ssr, tvb, offset, 4, FALSE);
				break;
			case EDP_DEVICE_TYPE_BRIDGE:
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_level1, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_trans, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_route, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_igmp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_gmrp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_gvrp, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_switch_option_8021q, tvb, offset, 4, FALSE);
				break;
			case EDP_DEVICE_TYPE_VLANMAN:
				break;
			case EDP_DEVICE_TYPE_NTSERVER:
			case EDP_DEVICE_TYPE_NTCLIENT:
			case EDP_DEVICE_TYPE_WIN95:
			case EDP_DEVICE_TYPE_WIN98:
			case EDP_DEVICE_TYPE_UNIXSERVER:
			case EDP_DEVICE_TYPE_UNIXCLIENT:
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_ad, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_dns, tvb, offset, 4, FALSE);
				proto_tree_add_item(edp_options_tree, hf_ismp_edp_end_station_option_dhcp, tvb, offset, 4, FALSE);
				break;
			case EDP_DEVICE_TYPE_ACCESSPOINT:
			default:
				break;
		}
		offset += 4;
		
		/* determine the number of neighbors and create EDP neighbors subtree */
		num_neighbors = tvb_get_ntohs(tvb, offset);
		proto_tree_add_item(edp_tree, hf_ismp_edp_num_neighbors, tvb, offset, 2, FALSE);
		offset += 2;
		if (num_neighbors > 0)
		{
			tvb_ensure_bytes_exist(tvb, offset, num_neighbors*10);
			if (tvb_reported_length_remaining(tvb, offset) >= (num_neighbors *10))
			{
				neighbors_ptr = tvb_get_ptr( tvb, offset, (num_neighbors*10) );
				edp_neighbors_ti = proto_tree_add_bytes_format(edp_tree, hf_ismp_edp_neighbors, tvb, 
					offset, num_neighbors*10, neighbors_ptr, "Neighbors:");
			}
			else
			{
				neighbors_ptr = tvb_get_ptr( tvb, offset, tvb_reported_length_remaining(tvb, offset) );
				edp_neighbors_ti = proto_tree_add_bytes_format(edp_tree, hf_ismp_edp_neighbors, tvb, 
					offset, num_neighbors *10, neighbors_ptr, "Neighbors:");
			}
			edp_neighbors_tree = proto_item_add_subtree(edp_neighbors_ti, ett_ismp_edp_neighbors);
			while ( neighbors_count < num_neighbors && tvb_reported_length_remaining(tvb, offset) >= 10)
			{
				edp_neighbors_leaf_ti = proto_tree_add_text(edp_neighbors_tree, tvb, offset, 10,
                        		        "Neighbor%d", (neighbors_count+1));
				edp_neighbors_leaf_tree = proto_item_add_subtree(edp_neighbors_leaf_ti, ett_ismp_edp_neighbors_leaf);

				proto_tree_add_text(edp_neighbors_leaf_tree, tvb, offset, 6,
					"MAC Address: %s", ether_to_str(tvb_get_ptr(tvb, offset, 6)));
				proto_tree_add_text(edp_neighbors_leaf_tree, tvb, offset, 4,
					"Assigned Neighbor State 0x%04x",tvb_get_ntohl(tvb, offset));
				offset += 10;
				neighbors_count++;
			}
			if (neighbors_count != num_neighbors)
			{
				proto_tree_add_text(edp_tree, tvb, offset, tvb_reported_length_remaining(tvb, offset),
				"MALFORMED PACKET");
				return;
			}
		}
		
		/* determine data remains, if so, count tuples
		   and create EDP tuples subtree */
		if (tvb_reported_length_remaining(tvb, offset) != 0 && 
			tvb_reported_length_remaining(tvb, offset) >= 2) 
		{
			num_tuples = tvb_get_ntohs(tvb, offset);
			proto_tree_add_item(edp_tree, hf_ismp_edp_num_tuples, tvb, offset, 2, FALSE);
			offset += 2;
		}
		else if (tvb_reported_length_remaining(tvb, offset) > 0) {
			proto_tree_add_text(edp_tree, tvb, offset, 
				tvb_reported_length_remaining(tvb, offset), "MALFORMED PACKET");
			return;
		}
		else
		{
			return;
		}

		/* start populating tuple information */
		if (num_tuples && tvb_reported_length_remaining(tvb, offset) >= 4)
		{
			tuples_ptr = tvb_get_ptr(tvb, offset, tvb_reported_length_remaining(tvb, offset));
			edp_tuples_ti = proto_tree_add_bytes_format(edp_tree, hf_ismp_edp_tuples, tvb,
				offset, tvb_reported_length_remaining(tvb, offset), tuples_ptr, "Tuples");
			edp_tuples_tree = proto_item_add_subtree(edp_tuples_ti, ett_ismp_edp_tuples);

			while ( (tuples_count < num_tuples) && (tvb_reported_length_remaining(tvb, offset) >= 4) )
			{

				tuple_length = tvb_get_ntohs(tvb, offset+2);
				edp_tuples_leaf_ti = proto_tree_add_text(edp_tuples_tree, tvb, offset, tuple_length,
					"Tuple%d", tuples_count+1);

				edp_tuples_leaf_tree = proto_item_add_subtree(edp_tuples_leaf_ti, ett_ismp_edp_tuples_leaf);

				tuple_type = tvb_get_ntohs(tvb, offset);
				proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, 2,
					"Tuple Type: %s(%d)", val_to_str( tuple_type, edp_tuple_types, "Unknown"), tuple_type );
				offset += 2;
				proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, 2,
					"Tuple Length: %d", tuple_length);
				tuple_length -= 4;
				offset += 2;
				
				if (tvb_reported_length_remaining(tvb, offset) >= tuple_length)
				{
					tvb_ensure_bytes_exist(tvb, offset, tuple_length);
					switch (tuple_type)
					{						
						case EDP_TUPLE_HOLD:
							proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
								"Hold Time = %d", tvb_get_ntohs(tvb, offset));
							break;
						case EDP_TUPLE_INT_NAME:
							proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
								"Interface Name = %s", tvb_format_text(tvb, offset, tuple_length));
							col_append_fstr(pinfo->cinfo, COL_INFO, ", ifName %s",
								tvb_format_text(tvb, offset, tuple_length));
							break;
						case EDP_TUPLE_SYS_DESCRIPT:
							proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
								"System Description = %s", tvb_format_text(tvb, offset, tuple_length));
							break;
						case EDP_TUPLE_IPX_ADDR:
							proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
								"Interface IPX_address = %s", 
								ipx_addr_to_str(tvb_get_ntohl(tvb, offset), 
								tvb_get_ptr(tvb, offset+4, tuple_length-4)));
							break;
						case EDP_TUPLE_UNKNOWN:
						default:
							proto_tree_add_text(edp_tuples_leaf_tree, tvb, offset, tuple_length,
								"Unknown Tuple Data %s", tvb_format_text(tvb, offset, tuple_length));
							break;
					}  
				}
				offset += tuple_length;

				tuples_count++;
				tuple_type = 0;
				tuple_length = 0;
			} 
			if (tuples_count != num_tuples)
			{
				proto_tree_add_text(edp_tree, tvb, offset, 
					tvb_reported_length_remaining(tvb, offset), "MALFORMED PACKET");
				return;
			}
			else
			{
				return;
			}
		}
			
	}
		

}
Example #17
0
static int
dissect_daap_one_tag(proto_tree *tree, tvbuff_t *tvb, int offset, int length)
{
   unsigned int tagname;
   int tagsize;
   int new_offset;
   proto_item *ti = NULL;
   proto_item *ti2 = NULL;
   proto_tree *new_tree = NULL;

   do {
      if (!tvb_offset_exists(tvb, offset)) 
	 break;

      tagname = tvb_get_ntohl(tvb, offset);
      tagsize = tvb_get_ntohl(tvb, offset+4);
      tvb_ensure_bytes_exist(tvb, offset, tagsize+8);
      ti = proto_tree_add_text(tree, tvb, offset, tagsize+8, 
			       "Tag: %c%c%c%c, Size: %d", 
			       tvb_get_guint8(tvb, offset),
			       tvb_get_guint8(tvb, offset+1),
			       tvb_get_guint8(tvb, offset+2),
			       tvb_get_guint8(tvb, offset+3),
			       tagsize);

      ti2 = proto_tree_add_item(tree, hf_daap_name, tvb, offset, 4, FALSE);
      PROTO_ITEM_SET_HIDDEN(ti2);
      ti2 = proto_tree_add_item(tree, hf_daap_size, tvb, offset+4, 4, FALSE);
      PROTO_ITEM_SET_HIDDEN(ti2);
      offset += 8;
      length -= 8;

      switch (tagname) {
      case daap_mcon:
      case daap_msrv:
      case daap_mccr:
      case daap_mdcl:
      case daap_mlog:
      case daap_mupd:
      case daap_avdb:
      case daap_mlcl:
      case daap_mlit:
      case daap_mbcl:
      case daap_adbs:
      case daap_aply:
      case daap_apso:
      case daap_mudl:
      case daap_abro:
      case daap_abal:
      case daap_abcp:
      case daap_abgn:
      case daap_prsv:
      case daap_arif:
	 /* Container tags */
	 new_tree = proto_item_add_subtree(ti, ett_daap_sub);
	 new_offset = dissect_daap_one_tag(new_tree, tvb, offset, 
					   tagsize);
	 break;
      case daap_minm:
      case daap_msts:
      case daap_mcnm:
      case daap_mcna:
      case daap_asal:
      case daap_asar:
      case daap_ascm:
      case daap_asfm:
      case daap_aseq:
      case daap_asgn:
      case daap_asdt:
      case daap_asul:
	 /* Tags contain strings */
	 proto_item_append_text(ti, ", Data: %s",
				tvb_format_text(tvb, offset, tagsize));
	 break;
      case daap_mper:
	 /* Tags conain uint64 */
	 proto_item_append_text(ti, ", Persistent Id: %" G_GINT64_MODIFIER "u", 
				tvb_get_ntoh64(tvb, offset));
	 break;
      case daap_mstt:
	 proto_item_append_text(ti, ", Status: %d", 
				tvb_get_ntohl(tvb, offset));
	 break;
      case daap_musr:
      case daap_msur:
	 proto_item_append_text(ti, ", Revision: %d", 
				tvb_get_ntohl(tvb, offset));
	 break;
      case daap_miid:
      case daap_mcti:
      case daap_mpco:
      case daap_mlid:
	 proto_item_append_text(ti, ", Id: %d", 
				tvb_get_ntohl(tvb, offset));
	 break;
      case daap_mrco:
      case daap_mtco:
      case daap_mimc:
      case daap_msdc:
	 proto_item_append_text(ti, ", Count: %d", 
				tvb_get_ntohl(tvb, offset));
	 break;
      case daap_mstm:
	 proto_item_append_text(ti, ", Timeout: %d seconds", 
				tvb_get_ntohl(tvb, offset));
	 break;
      case daap_asda:
      case daap_asdm:
      case daap_assr:
      case daap_assz:
      case daap_asst:
      case daap_assp:
      case daap_astm:
      case daap_aeNV:
	 /* Tags conain uint32 */
	 proto_item_append_text(ti, ", Data: %d", 
				tvb_get_ntohl(tvb, offset));
	 break;

      case daap_mcty:
      case daap_asbt:
      case daap_asbr:
      case daap_asdc:
      case daap_asdn:
      case daap_astc:
      case daap_astn:
      case daap_asyr:
	 /* Tags conain uint16 */
	 proto_item_append_text(ti, ", Data: %d", 
				tvb_get_ntohs(tvb, offset));
	 break;

      case daap_mikd:
      case daap_msau:
      case daap_msty:
      case daap_asrv:
      case daap_asur:
      case daap_asdk:
	 /* Tags conain uint8 */
	 proto_item_append_text(ti, ", Data: %d", 
				tvb_get_guint8(tvb, offset));

	 break;

      case daap_mslr:
      case daap_msal:
      case daap_msup:
      case daap_mspi:
      case daap_msex:
      case daap_msbr:
      case daap_msqy:
      case daap_msix:
      case daap_msrs:
      case daap_asco:
      case daap_asdb:
      case daap_abpl:
      case daap_aeSP:
	 /* Tags ARE boolean. Data is (uint8), but it seems
	  * the value is always zero. So, if the tag is present
	  * the "bool" is true. 
	  */
	 proto_item_append_text(ti, ", Data: True");
	 break;

      case daap_mpro:
      case daap_apro:
	 /* Tags conain version (uint32) */
	 proto_item_append_text(ti, ", Version: %d.%d.%d.%d",
				tvb_get_guint8(tvb, offset),
				tvb_get_guint8(tvb, offset+1),
				tvb_get_guint8(tvb, offset+2),
				tvb_get_guint8(tvb, offset+3));
	 break;

      default: 
	 break;
      }
      offset += tagsize;
      length -= tagsize;
   } while (length > 0);
   return offset;
}
void dissect_nhrp_mand(tvbuff_t *tvb,
					   packet_info *pinfo,
					   proto_tree *tree,
					   gint *pOffset,
					   gint mandLen,
					   oui_info_t *oui_info,
					   e_nhrp_hdr *hdr,
					   guint *srcLen,
					   gboolean codeinfo)
{
	gint	offset = *pOffset;
	gint	mandEnd = offset + mandLen;
	guint8	ssl, shl;
	guint16	flags;
	guint	dstLen;
	gboolean isReq = 0;
	gboolean isErr = 0;
	gboolean isInd = 0;

	proto_item *nhrp_tree_item = NULL;
	proto_item *flag_item = NULL;
	proto_tree *nhrp_tree = NULL;
	proto_tree *flag_tree = NULL;

	tvb_ensure_bytes_exist(tvb, offset, mandLen);

	switch (hdr->ar_op_type)
	{
	case NHRP_RESOLUTION_REPLY:
	case NHRP_REGISTRATION_REPLY:
	case NHRP_PURGE_REPLY:
		break;
	case NHRP_RESOLUTION_REQ:
	case NHRP_REGISTRATION_REQ:
	case NHRP_PURGE_REQ:
		isReq = 1;
		break;
	case NHRP_ERROR_INDICATION:	/* This needs special treatment */
		isErr = 1;
		isInd = 1;
		break;
	case NHRP_TRAFFIC_INDICATION:
		isInd = 1;
		break;
	}
	nhrp_tree_item = proto_tree_add_text(tree, tvb, offset, mandLen, "NHRP Mandatory Part");
	nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_mand);

	*srcLen = tvb_get_guint8(tvb, offset);
	proto_tree_add_item(nhrp_tree, hf_nhrp_src_proto_len, tvb, offset, 1, FALSE);
	offset += 1;

	dstLen = tvb_get_guint8(tvb, offset);
	proto_tree_add_item(nhrp_tree, hf_nhrp_dst_proto_len, tvb, offset, 1, FALSE);
	offset += 1;

	if (!isInd) {
		flags = tvb_get_ntohs(tvb, offset);
		flag_item = proto_tree_add_uint(nhrp_tree, hf_nhrp_flags, tvb, offset, 2, flags);
		flag_tree = proto_item_add_subtree(flag_item, ett_nhrp_mand_flag);

		switch (hdr->ar_op_type)
		{
		case NHRP_RESOLUTION_REQ:
		case NHRP_RESOLUTION_REPLY:
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_Q, tvb, offset, 2, flags);
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_A, tvb, offset, 2, flags);
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_D, tvb, offset, 2, flags);
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_U1, tvb, offset, 2, flags);
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_S, tvb, offset, 2, flags);
			break;
		case NHRP_REGISTRATION_REQ:
		case NHRP_REGISTRATION_REPLY:
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_U2, tvb, offset, 2, flags);
			break;

		case NHRP_PURGE_REQ:
		case NHRP_PURGE_REPLY:
			proto_tree_add_boolean(flag_tree, hf_nhrp_flag_N, tvb, offset, 2, flags);
			break;
		}
		proto_tree_add_boolean(flag_tree, hf_nhrp_flag_NAT, tvb, offset, 2, flags);

		offset += 2;

		col_append_fstr(pinfo->cinfo, COL_INFO, ", ID=%u", tvb_get_ntohl(tvb, offset));
		proto_tree_add_item(nhrp_tree, hf_nhrp_request_id, tvb, offset, 4, FALSE);
		offset += 4;
	}
	else if (isErr) {
		offset += 2;

		col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
			val_to_str(tvb_get_ntohs(tvb, offset), nhrp_error_code_vals, "Unknown Error (%u)"));
		proto_tree_add_item(nhrp_tree, hf_nhrp_error_code, tvb, offset, 2, FALSE);
		offset += 2;

		proto_tree_add_item(nhrp_tree, hf_nhrp_error_offset, tvb, offset, 2, FALSE);
		offset += 2;
	}
	else {
		offset += 6;
	}

	shl = NHRP_SHTL_LEN(hdr->ar_shtl);
	if (shl) {
		switch (hdr->ar_afn) {

		case AFNUM_INET:
			if (shl == 4)
				proto_tree_add_item(nhrp_tree, hf_nhrp_src_nbma_addr, tvb, offset, 4, FALSE);
			else {
				proto_tree_add_text(nhrp_tree, tvb, offset, shl,
				    "Source NBMA Address: %s",
				    tvb_bytes_to_str(tvb, offset, shl));
			}
			break;

		default:
			proto_tree_add_text(nhrp_tree, tvb, offset, shl,
			    "Source NBMA Address: %s",
			    tvb_bytes_to_str(tvb, offset, shl));
			break;
		}
		offset += shl;
	}

	ssl = NHRP_SHTL_LEN(hdr->ar_sstl);
	if (ssl) {
		proto_tree_add_text(nhrp_tree, tvb, offset, ssl,
							"Source NBMA Sub Address: %s",
							tvb_bytes_to_str(tvb, offset, ssl));
		offset += ssl;
	}

	if (*srcLen == 4) {
		proto_tree_add_item(nhrp_tree, hf_nhrp_src_prot_addr, tvb, offset, 4, FALSE);
		offset += 4;
	}
	else if (*srcLen) {
		proto_tree_add_text(nhrp_tree, tvb, offset, *srcLen,
							"Source Protocol Address: %s",
							tvb_bytes_to_str(tvb, offset, *srcLen));
		offset += *srcLen;
	}

	if (dstLen == 4) {
		proto_tree_add_item(nhrp_tree, hf_nhrp_dst_prot_addr, tvb, offset, 4, FALSE);
		offset += 4;
	}
	else if (dstLen) {
		proto_tree_add_text(nhrp_tree, tvb, offset, dstLen,
							"Destination Protocol Address: %s",
							tvb_bytes_to_str(tvb, offset, dstLen));
		offset += dstLen;
	}

	if (isInd) {
		gboolean save_in_error_pkt;
		gint pkt_len = mandEnd - offset;
		proto_item *ind_tree_item = proto_tree_add_text(tree, tvb, offset, pkt_len, "Packet Causing Indication");
		proto_tree *ind_tree = proto_item_add_subtree(ind_tree_item, ett_nhrp_indication);
		gboolean dissected;
		tvbuff_t *sub_tvb;

		save_in_error_pkt = pinfo->in_error_pkt;
		pinfo->in_error_pkt = TRUE;
		sub_tvb = tvb_new_subset_remaining(tvb, offset);
		if (isErr) {
			_dissect_nhrp(sub_tvb, pinfo, ind_tree, TRUE, FALSE);
		}
		else {
			if (hdr->ar_pro_type <= 0xFF) {
				/* It's an NLPID */
				if (hdr->ar_pro_type == NLPID_SNAP) {
					/*
					 * Dissect based on the SNAP OUI
					 * and PID.
					 */
					if (hdr->ar_pro_type_oui == 0x000000) {
						/*
						 * "Should not happen", as
						 * the protocol type should
						 * be the Ethertype, but....
						 */
						dissected = dissector_try_port(
						    ethertype_subdissector_table,
						    hdr->ar_pro_type_pid,
						    sub_tvb, pinfo, ind_tree);
					} else {
						/*
						 * If we have a dissector
						 * table, use it, otherwise
						 * just dissect as data.
						 */
						if (oui_info != NULL) {
							dissected = dissector_try_port(
							    oui_info->table,
							    hdr->ar_pro_type_pid,
							    sub_tvb, pinfo,
							    ind_tree);
						} else
							dissected = FALSE;
					}
				} else {
					/*
					 * Dissect based on the NLPID.
					 */
					dissected = dissector_try_port(
					    osinl_subdissector_table,
					    hdr->ar_pro_type, sub_tvb, pinfo,
					    ind_tree) ||
					            dissector_try_port(
					    osinl_excl_subdissector_table,
					    hdr->ar_pro_type, sub_tvb, pinfo,
					    ind_tree);
				}
			} else if (hdr->ar_pro_type <= 0x3FF) {
				/* Reserved for future use by the IETF */
				dissected = FALSE;
			} else if (hdr->ar_pro_type <= 0x04FF) {
				/* Allocated for use by the ATM Forum */
				dissected = FALSE;
			} else if (hdr->ar_pro_type <= 0x05FF) {
				/* Experimental/Local use */
				dissected = FALSE;
			} else {
				dissected = dissector_try_port(
				    ethertype_subdissector_table,
				    hdr->ar_pro_type, sub_tvb, pinfo, ind_tree);
			}
			if (!dissected) {
				call_dissector(data_handle, sub_tvb, pinfo,
				    ind_tree);
			}
		}
		pinfo->in_error_pkt = save_in_error_pkt;
		offset = mandEnd;
	}

	/* According to RFC 2332, section 5.2.7, there shouldn't be any extensions
	 * in the Error Indication packet. */
	if (isErr && tvb_reported_length_remaining(tvb, offset)) {
		expert_add_info_format(pinfo, tree, PI_MALFORMED, PI_ERROR,
			"Extensions not allowed per RFC2332 section 5.2.7");
	}

	dissect_cie_list(tvb, pinfo, nhrp_tree, offset, mandEnd, hdr, isReq, codeinfo);

	*pOffset = mandEnd;
}
void dissect_nhrp_ext(tvbuff_t *tvb,
					  packet_info *pinfo,
					  proto_tree *tree,
					  gint *pOffset,
					  gint extLen,
					  e_nhrp_hdr *hdr,
					  guint srcLen,
					  gboolean nested)
{
	gint	offset = *pOffset;
	gint	extEnd = offset + extLen;

	proto_item *nhrp_tree_item = NULL;
	proto_tree *nhrp_tree = NULL;
	proto_item *ti = NULL;

	tvb_ensure_bytes_exist(tvb, offset, extLen);

	while ((offset + 4) <= extEnd)
	{
		gint extTypeC = tvb_get_ntohs(tvb, offset);
		gint extType = extTypeC & 0x3FFF;
		guint len  = tvb_get_ntohs(tvb, offset+2);

		if ((extType == NHRP_EXT_NAT_ADDRESS) && (len == 8)) {
			/* Assume it's not really a Cisco NAT extension, but a device
			 * capabilities extension instead (see RFC 2735). */
			nhrp_tree_item =  proto_tree_add_text(tree, tvb, offset,
				len + 4, "Device Capabilities Extension");
		}
		else {
			nhrp_tree_item =  proto_tree_add_text(tree, tvb, offset,
				len + 4, "%s",
				val_to_str(extType, ext_type_vals, "Unknown (%u)"));
		}
		nhrp_tree = proto_item_add_subtree(nhrp_tree_item, ett_nhrp_ext);
		proto_tree_add_boolean(nhrp_tree, hf_nhrp_ext_C, tvb, offset, 2, extTypeC);
		proto_tree_add_item(nhrp_tree, hf_nhrp_ext_type, tvb, offset, 2, FALSE);
		offset += 2;

		proto_tree_add_item(nhrp_tree, hf_nhrp_ext_len, tvb, offset, 2, FALSE);
		offset += 2;

		if (len && (extType != NHRP_EXT_NULL)) {
			tvb_ensure_bytes_exist(tvb, offset, len);
			if ((extType == NHRP_EXT_NAT_ADDRESS) && (len == 8)) {
				/* Assume it's not really a Cisco NAT extension, but a device
				 * capabilities extension instead (see RFC 2735). */
				proto_item *devcap_item;
				proto_tree *devcap_tree;
				proto_item *cap_item;
				proto_tree *cap_tree;

				devcap_item = proto_tree_add_text(nhrp_tree, tvb, offset, len,
					"Extension Data: Src is %sVPN-aware; Dst is %sVPN-aware",
					tvb_get_ntohl(tvb, offset) & 1 ? "" : "non-",
					tvb_get_ntohl(tvb, offset + 4) & 1 ? "" : "non-");
				devcap_tree = proto_item_add_subtree(devcap_item, ett_nhrp_devcap_ext);
				cap_item = proto_tree_add_item(devcap_tree, hf_nhrp_devcap_ext_srccap, tvb, offset, 4, FALSE);
				cap_tree = proto_item_add_subtree(cap_item, ett_nhrp_devcap_ext_srccap);
				proto_tree_add_item(cap_tree, hf_nhrp_devcap_ext_srccap_V, tvb, offset, 4, FALSE);

				cap_item = proto_tree_add_item(devcap_tree, hf_nhrp_devcap_ext_dstcap, tvb, offset + 4, 4, FALSE);
				cap_tree = proto_item_add_subtree(cap_item, ett_nhrp_devcap_ext_dstcap);
				proto_tree_add_item(cap_tree, hf_nhrp_devcap_ext_dstcap_V, tvb, offset + 4, 4, FALSE);
				goto skip_switch;
			}

			switch (extType) {
			case NHRP_EXT_RESP_ADDR:
			case NHRP_EXT_FWD_RECORD:
			case NHRP_EXT_REV_RECORD:
			case NHRP_EXT_NAT_ADDRESS:
				dissect_cie_list(tvb, pinfo, nhrp_tree,
				    offset, offset + len, hdr, 0, FALSE);
				break;

			case NHRP_EXT_AUTH:
			case NHRP_EXT_MOBILE_AUTH:
				if (len < (4 + srcLen)) {
					ti = proto_tree_add_text(nhrp_tree, tvb, offset, len,
						"Malformed Extension: %s",
						tvb_bytes_to_str(tvb, offset, len));
					expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
						"Incomplete Authentication Extension");
				}
				else {
					proto_item *auth_item;
					proto_tree *auth_tree;

					auth_item = proto_tree_add_text(nhrp_tree, tvb, offset, len,
						"Extension Data: SPI=%u: Data=%s", tvb_get_ntohs(tvb, offset + 2),
						tvb_bytes_to_str(tvb, offset + 4, len - 4));
					auth_tree = proto_item_add_subtree(auth_item, ett_nhrp_auth_ext);
					proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_reserved, tvb, offset, 2, FALSE);
					proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_spi, tvb, offset + 2, 2, FALSE);
					if (srcLen == 4)
						proto_tree_add_item(auth_tree, hf_nhrp_auth_ext_src_addr, tvb, offset + 4, 4, FALSE);
					else if (srcLen) {
						proto_tree_add_text(auth_tree, tvb, offset + 4, srcLen,
							"Source Address: %s",
							tvb_bytes_to_str(tvb, offset + 4, srcLen));
					}
					if (len > (4 + srcLen)) {
						proto_tree_add_text(auth_tree, tvb, offset + 4 + srcLen, len - (4 + srcLen),
							"Data: %s", tvb_bytes_to_str(tvb, offset + 4 + srcLen, len - (4 + srcLen)));
					}
				}
				break;

			case NHRP_EXT_VENDOR_PRIV:
				if (len < 3) {
					ti = proto_tree_add_text(nhrp_tree, tvb, offset, len,
						"Malformed Extension: %s",
						tvb_bytes_to_str(tvb, offset, len));
					expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
						"Incomplete Vendor-Private Extension");
				}
				else {
					proto_item *vendor_item;
					proto_tree *vendor_tree;
					gchar manuf[3];

					tvb_memcpy(tvb, manuf, offset, 3);
					vendor_item = proto_tree_add_text(nhrp_tree, tvb, offset, len,
						"Extension Data: Vendor ID=%s, Data=%s", get_manuf_name(manuf),
						tvb_bytes_to_str(tvb, offset + 3, len - 3));
					vendor_tree = proto_item_add_subtree(vendor_item, ett_nhrp_vendor_ext);
					proto_tree_add_bytes_format(vendor_tree, hf_nhrp_vendor_ext_id, tvb,
						offset, 3, manuf, "Vendor ID: %s", get_manuf_name(manuf));
					if (len > 3) {
						proto_tree_add_text(vendor_tree, tvb, offset + 3, len - 3,
							"Data: %s", tvb_bytes_to_str(tvb, offset + 3, len - 3));
					}
				}
				break;

			default:
				proto_tree_add_text(nhrp_tree, tvb, offset, len,
					"Extension Value: %s",
					tvb_bytes_to_str(tvb, offset, len));
				break;
			}
skip_switch:
			offset += len;
		}

		if (!nested) {
			len = tvb_reported_length_remaining(tvb, offset);
			if ((extType == NHRP_EXT_NULL) && len) {
				ti = proto_tree_add_text(tree, tvb, offset, len,
					"Unknown Data (%d bytes)", len);
				expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
					"Superfluous data follows End Extension");
				break;
			}
		}
	}

	*pOffset = extEnd;
}
Example #20
0
/* nopad == TRUE : Do not add any padding before this string
 * exactlen == TRUE : len contains the exact len of the string in bytes.
 * bc: pointer to variable with amount of data left in the byte parameters
 *   region
 */
const gchar *
get_unicode_or_ascii_string(tvbuff_t *tvb, int *offsetp,
			    gboolean useunicode, int *len, gboolean nopad, gboolean exactlen,
			    guint16 *bcp)
{
	gchar *cur;
	const gchar *string;
	int string_len = 0;
	int copylen;
	gboolean overflow = FALSE;

	if (*bcp == 0) {
		/* Not enough data in buffer */
		return NULL;
	}

	if (useunicode) {
		if ((!nopad) && (*offsetp % 2)) {
			(*offsetp)++;   /* Looks like a pad byte there sometimes */
			(*bcp)--;

			if (*bcp == 0) {
				/* Not enough data in buffer */
				return NULL;
			}
		}

		if(exactlen){
			string_len = *len;
			if (string_len < 0) {
				/* This probably means it's a very large unsigned number; just set
				   it to the largest signed number, so that we throw the appropriate
				   exception. */
				string_len = INT_MAX;
			}
		}

		string = unicode_to_str(tvb, *offsetp, &string_len, exactlen, *bcp);

	} else {
		if(exactlen){
			/*
			 * The string we return must be null-terminated.
			 */
			cur=ep_alloc(MAX_UNICODE_STR_LEN+3+1);
			copylen = *len;

			if (copylen < 0) {
				/* This probably means it's a very large unsigned number; just set
				   it to the largest signed number, so that we throw the appropriate
				   exception. */
				copylen = INT_MAX;
			}

			tvb_ensure_bytes_exist(tvb, *offsetp, copylen);

			if (copylen > MAX_UNICODE_STR_LEN) {
				copylen = MAX_UNICODE_STR_LEN;
				overflow = TRUE;
			}

			tvb_memcpy(tvb, (guint8 *)cur, *offsetp, copylen);
			cur[copylen] = '\0';

			if (overflow)
				g_strlcat(cur, "...",MAX_UNICODE_STR_LEN+3+1);

			string_len = *len;
			string = cur;
		} else {
			string = tvb_get_const_stringz(tvb, *offsetp, &string_len);
		}
	}

	*len = string_len;
	return string;
}
Example #21
0
/* G.7041 6.1.2 GFP payload area */
static void
dissect_gfp_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *gfp_tree, guint *offset, guint payload_len)
{
    tvbuff_t *payload_tvb;
    proto_item *type_ti = NULL;
    proto_item *fcs_ti;
    proto_tree *fcs_tree = NULL;
    guint pti, pfi, exi, upi;
    guint fcs, fcs_calc;
    guint fcs_len = 0;

    /* G.7041 6.1.2.3 Payload area scrambling
     * Note that payload when sent on the wire is scrambled as per ATM
     * with a 1 + x^43 multiplicative scrambler. Likely already removed by
     * the time we get a capture file (as with ATM). Could have a pref,
     * but if it's present we have to save state over subsequent frames,
     * always would fail to decode the first 43 payload bytes of a capture. */

    /* G.7041 6.1.2.1 Payload Header - at least 4 bytes */
    tvb_ensure_bytes_exist(tvb, *offset, 4);
    payload_len -= 4;

    /* G.7041 6.1.2.1.1 GFP type field - mandatory 2 bytes */
    pti = tvb_get_bits8(tvb, 8*(*offset), 3);
    pfi = tvb_get_bits8(tvb, 8*(*offset)+3, 1);
    exi = tvb_get_bits8(tvb, 8*(*offset)+4, 4);
    upi = tvb_get_guint8(tvb, *offset+1);
    p_add_proto_data(pinfo->pool, pinfo, proto_gfp, 0, GUINT_TO_POINTER(upi));

    col_add_str(pinfo->cinfo, COL_INFO, val_to_str(pti, gfp_pti_vals, "Reserved PTI (%d)"));
    if (pti == GFP_USER_DATA ||
            pti == GFP_MANAGEMENT_COMMUNICATIONS) {
        /* G.7041 Table 6-3 - GFP_MANAGEMENT_COMMUNICATIONS
         * uses the same UPI table as USER_DATA, though
         * "not all of these UPI types are applicable" in that case. */
        type_ti = proto_tree_add_bitmask_with_flags(gfp_tree, tvb, *offset, hf_gfp_type,
                  ett_gfp_type, gfp_type_data_fields, ENC_BIG_ENDIAN, BMT_NO_FLAGS);
        col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", rval_to_str(upi, gfp_upi_data_rvals, "Unknown 0x%02x"));
    } else if (pti == GFP_CLIENT_MANAGEMENT) {
        /* G.7041 Table 6-4 */
        type_ti = proto_tree_add_bitmask_with_flags(gfp_tree, tvb, *offset, hf_gfp_type,
                  ett_gfp_type, gfp_type_management_fields, ENC_BIG_ENDIAN, BMT_NO_FLAGS);
        col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", rval_to_str(upi, gfp_upi_management_rvals, "Unknown 0x%02x"));
    }

    /* G.7041 6.1.2.1.2 Type HEC (tHEC) - mandatory 2 bytes */
    gfp_add_hec_tree(tvb, pinfo, gfp_tree, offset, 2, hf_gfp_thec, hf_gfp_thec_status, &ei_gfp_thec_bad);

    switch (exi) {
    case GFP_EXT_NULL:
        /* G.7041 6.1.2.1.3.1 Null extension header */
        break;

    case GFP_EXT_LINEAR:
        /* G.7041 6.1.2.1.3.2 Extension header for a linear frame */
        if (payload_len < 4) {
            expert_add_info(pinfo, type_ti, &ei_gfp_exi_short);
            payload_len = 0;
        }
        else {
            payload_len -= 4;
        }
        proto_tree_add_item(gfp_tree, hf_gfp_cid, tvb, *offset, 1, ENC_BIG_ENDIAN);
        /* Next byte spare field, reserved */

        /* 6.1.2.1.4 Extension HEC field */
        gfp_add_hec_tree(tvb, pinfo, gfp_tree, offset, 2, hf_gfp_ehec, hf_gfp_ehec_status, &ei_gfp_ehec_bad);
        break;
    case GFP_EXT_RING:
    /* 6.1.2.1.3.3 Extension header for a ring frame */
    /* "For further study." Undefined so fall through */
    default:
        /* Reserved */
        /* TODO: Mark as error / unhandled? */
        break;
    }

    proto_item_set_end(gfp_tree, tvb, *offset);

    if (pfi == 1) { /* 6.1.2.2.1 Payload FCS field present */
        if (payload_len < 4) {
            expert_add_info(pinfo, type_ti, &ei_gfp_pfi_short);
            fcs_len = payload_len;
            payload_len = 0;
        } else {
            fcs_len = 4;
            payload_len -= 4;
        }

        proto_tree_set_appendix(gfp_tree, tvb, *offset + payload_len, fcs_len);
        fcs = tvb_get_ntohl(tvb, *offset + payload_len);
        /* Same CRC32 as ATM */
        /* As with ATM, we can either compute the CRC as it would be
         * calculated and compare (last step involves taking the complement),
         * or we can include the passed CRC in the input and check to see
         * if the remainder is a known value. I like the first method
         * only because it lets us display what we should have received. */
        /* Method 1: */
        fcs_calc = crc32_mpeg2_tvb_offset(tvb, *offset, payload_len);
        if (fcs == ~fcs_calc) {
            fcs_ti = proto_tree_add_uint_format_value(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs, "0x%08x [correct]", fcs);
            fcs_tree = proto_item_add_subtree(fcs_ti, ett_gfp_fcs);
            fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_good, tvb, *offset+payload_len, 4, TRUE);
            PROTO_ITEM_SET_GENERATED(fcs_ti);
            fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_bad, tvb, *offset+payload_len, 4, FALSE);
            PROTO_ITEM_SET_GENERATED(fcs_ti);
        } else {
            fcs_ti = proto_tree_add_uint_format_value(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs, "0x%08x [incorrect, should be 0x%08x]", fcs, fcs_calc);
            fcs_tree = proto_item_add_subtree(fcs_ti, ett_gfp_fcs);
            fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_good, tvb, *offset+payload_len, 4, FALSE);
            PROTO_ITEM_SET_GENERATED(fcs_ti);
            fcs_ti = proto_tree_add_boolean(fcs_tree, hf_gfp_fcs_bad, tvb, *offset+payload_len, 4, TRUE);
            PROTO_ITEM_SET_GENERATED(fcs_ti);
            expert_add_info(pinfo, fcs_ti, &ei_gfp_fcs_bad);
        }
        /* Method 2: */
        /* fcs_calc = crc32_mpeg2_tvb_offset(tvb, *offset, payload_len+4);
        fcs_ti = proto_tree_add_uint(gfp_tree, hf_gfp_fcs, tvb, *offset+payload_len, 4, fcs);
        proto_item_append_text(fcs_ti, (fcs_calc == 0xC704DD7B) ? " [correct]" : " [incorrect]"); */
    }

    /* Some client frames we can do. Others are not implemented yet.
     * Transparent mode types are much trickier than frame-mapped,
     * since they requires reassembling streams across multiple GFP packets. */
    payload_tvb = tvb_new_subset_length(tvb, *offset, payload_len);
    switch (pti) {
    case GFP_USER_DATA:
    case GFP_MANAGEMENT_COMMUNICATIONS:
        if (!dissector_try_uint(gfp_dissector_table, upi, payload_tvb, pinfo, tree)) {
            expert_add_info_format(pinfo, type_ti, &ei_gfp_payload_undecoded, "Payload type 0x%02x (%s) unsupported", upi, rval_to_str_const(upi, gfp_upi_data_rvals, "UNKNOWN"));
            call_data_dissector(payload_tvb, pinfo, tree);
        }
        break;

    case GFP_CLIENT_MANAGEMENT:
        call_data_dissector(payload_tvb, pinfo, tree);
        break;

    default:
        break;
    }
    *offset += payload_len;
    *offset += fcs_len;
}