Exemple #1
0
static void
dissect_tzsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree *tzsp_tree = NULL;
	proto_item *ti = NULL;
	int pos = 0;
	tvbuff_t *next_tvb;
	guint16 encapsulation = 0;
	int wtap_encap;
	dissector_handle_t encap_dissector;
	const char *encap_name;
	const char *info;
	guint8 type;

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

	type = tvb_get_guint8(tvb, 1);

	/* Find the dissector. */
	encapsulation = tvb_get_ntohs(tvb, 2);
	if (encapsulation != 0) {
		wtap_encap = tzsp_encap_to_wtap_encap(encapsulation);
		if (wtap_encap != -1 &&
		    (encap_dissector = dissector_get_uint_handle(encap_dissector_table, wtap_encap))) {
			encap_name = dissector_handle_get_short_name(encap_dissector);
		}
		else {
			encap_name = "Unknown";
		}
		info = encap_name;
	}
	else {
		wtap_encap = -1;
		encap_name = "Nothing";
		info = val_to_str(type, tzsp_type, "Unknown (%u)");
	}

	col_add_str(pinfo->cinfo, COL_INFO, info);

	if (tree) {
		/* Adding TZSP item and subtree */
		ti = proto_tree_add_protocol_format(tree, proto_tzsp, tvb, 0,
		    -1, "TZSP: %s: ", info);
		tzsp_tree = proto_item_add_subtree(ti, ett_tzsp);

		proto_tree_add_item (tzsp_tree, hf_tzsp_version, tvb, 0, 1,
					ENC_BIG_ENDIAN);
		proto_tree_add_uint (tzsp_tree, hf_tzsp_type, tvb, 1, 1,
					type);
		proto_tree_add_uint_format (tzsp_tree, hf_tzsp_encap, tvb, 2, 2,
					encapsulation, "Encapsulates: %s (%d)",
					encap_name, encapsulation);
	}

	/*
	 * XXX - what about TZSP_CONFIG frames?
	 *
	 * The MIB at
	 *
	 *	http://web.archive.org/web/20021221195733/http://www.networkchemistry.com/support/appnotes/SENSOR-MIB
	 *
	 * seems to indicate that you can configure the probe using SNMP;
	 * does TZSP_CONFIG also support that?  An old version of Kismet
	 * included code to control a Network Chemistry WSP100 sensor:
	 *
	 *	https://www.kismetwireless.net/code-old/svn/tags/kismet-2004-02-R1/wsp100source.cc
	 *
	 * and it used SNMP to configure the probe.
	 */
	if (type != TZSP_NULL && type != TZSP_PORT) {
		pos = add_option_info(tvb, 4, tzsp_tree, ti);

		if (tree)
			proto_item_set_end(ti, tvb, pos);
		next_tvb = tvb_new_subset_remaining(tvb, pos);
		if (encapsulation != 0
		    && (wtap_encap == -1
			|| !dissector_try_uint(encap_dissector_table, wtap_encap,
				next_tvb, pinfo, tree))) {

			col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
			col_add_fstr(pinfo->cinfo, COL_INFO, "TZSP_ENCAP = %u",
				    encapsulation);
			call_dissector(data_handle, next_tvb, pinfo, tree);
		}
	}
}
static void
dissect_acap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	gboolean        is_request;
	proto_tree      *acap_tree, *reqresp_tree;
	proto_item      *ti, *hidden_item;
	gint			offset = 0;
	const guchar	*line;
	gint			next_offset;
	int				linelen;
	int				tokenlen;
	const guchar	*next_token;

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

	/*
	 * Find the end of the first 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);

	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).
	 */
	col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
	    is_request ? "Request" : "Response",
	    format_text(line, linelen));

	if (tree) {
		ti = proto_tree_add_item(tree, hfi_acap, tvb, offset, -1,
		    ENC_NA);
		acap_tree = proto_item_add_subtree(ti, ett_acap);

		if (is_request) {
			hidden_item = proto_tree_add_boolean(acap_tree,
			    &hfi_acap_request, tvb, 0, 0, TRUE);
			PROTO_ITEM_SET_HIDDEN(hidden_item);
		} else {
			hidden_item = proto_tree_add_boolean(acap_tree,
			    &hfi_acap_response, tvb, 0, 0, TRUE);
			PROTO_ITEM_SET_HIDDEN(hidden_item);
		}

		/*
		 * Put the line into the protocol tree.
		 */
		ti = proto_tree_add_text(acap_tree, tvb, offset,
		    next_offset - offset, "%s",
		    tvb_format_text(tvb, offset, next_offset - offset));
		reqresp_tree = proto_item_add_subtree(ti, ett_acap_reqresp);

		/*
		 * Show the first 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) {
			if (is_request) {
				proto_tree_add_text(reqresp_tree, tvb, offset,
				    tokenlen, "Request Tag: %s",
				    format_text(line, tokenlen));
			} else {
				proto_tree_add_text(reqresp_tree, tvb, offset,
				    tokenlen, "Response Tag: %s",
				    format_text(line, tokenlen));
			}
			offset += (int)(next_token - line);
			linelen -= (int)(next_token - line);
			line = next_token;
		}

		/*
		 * Add the rest of the line as request or reply data.
		 */
		if (linelen != 0) {
			if (is_request) {
				proto_tree_add_text(reqresp_tree, tvb, offset,
				    linelen, "Request: %s",
				    format_text(line, linelen));
			} else {
				proto_tree_add_text(reqresp_tree, tvb, offset,
				    linelen, "Response: %s",
				    format_text(line, linelen));
			}
		}

		/*
		 * XXX - show the rest of the frame; this requires that
		 * we handle literals, quoted strings, continuation
		 * responses, etc..
		 *
		 * This involves a state machine, and attaching
		 * state information to the packets.
		 */
	}
}
/*
 * Name: dissect_isis()
 *
 * Description:
 *	Main entry area for isis de-mangling.  This will build the
 *	main isis tree data and call the sub-protocols as needed.
 *
 * Input:
 *	tvbuff_t * : tvbuffer for packet data
 *	packet_info * : info for current packet
 *	proto_tree * : tree of display data.  May be NULL.
 *
 * Output:
 *	void, but we will add to the proto_tree if it is not NULL.
 */
static void
dissect_isis(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item *ti;
	proto_tree *isis_tree = NULL;
	int offset = 0;
	guint8 isis_version;
	guint8 isis_header_length;
	guint8 isis_type_reserved;
	guint8 isis_type;
	guint8 isis_system_id_len;

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

	isis_version = tvb_get_guint8(tvb, 2);
	if (isis_version != ISIS_REQUIRED_VERSION){
		if (check_col(pinfo->cinfo, COL_INFO)) {
			col_add_fstr(pinfo->cinfo, COL_INFO,
				"Unknown ISIS version (%u vs %u)",
				isis_version, ISIS_REQUIRED_VERSION );
		}
		isis_dissect_unknown(tvb, tree, 0,
			"Unknown ISIS version (%d vs %d)",
			isis_version, ISIS_REQUIRED_VERSION);
		return;
	}

	if (tree) {
		ti = proto_tree_add_item(tree, proto_isis, tvb, 0, -1, FALSE);
		isis_tree = proto_item_add_subtree(ti, ett_isis);
	}

	if (tree) {
		proto_tree_add_item(isis_tree, hf_isis_irpd, tvb, offset, 1,
			FALSE );
	}
	offset += 1;

	isis_header_length = tvb_get_guint8(tvb, offset);
	if (tree) {
		proto_tree_add_uint(isis_tree, hf_isis_header_length, tvb,
			offset, 1, isis_header_length );
	}
	offset += 1;

	if (tree) {
		proto_tree_add_uint(isis_tree, hf_isis_version, tvb,
			offset, 1, isis_version );
	}
	offset += 1;

	isis_system_id_len = tvb_get_guint8(tvb, offset);
	if (tree) {
		proto_tree_add_uint(isis_tree, hf_isis_system_id_length, tvb,
			offset, 1, isis_system_id_len );
	}
	offset += 1;

	isis_type_reserved = tvb_get_guint8(tvb, offset);
	isis_type = isis_type_reserved & ISIS_TYPE_MASK;
	if (check_col(pinfo->cinfo, COL_INFO)) {
		col_add_str(pinfo->cinfo, COL_INFO,
			val_to_str ( isis_type, isis_vals, "Unknown (0x%x)" ) );
	}
	if (tree) {
		proto_tree_add_uint_format(isis_tree, hf_isis_type, tvb,
			offset, 1, isis_type,
			"PDU Type           : %s (R:%s%s%s)",
			val_to_str(isis_type, isis_vals, "Unknown (0x%x)"),
			(isis_type_reserved & ISIS_R8_MASK) ? "1" : "0",
			(isis_type_reserved & ISIS_R7_MASK) ? "1" : "0",
			(isis_type_reserved & ISIS_R6_MASK) ? "1" : "0");
	}
	offset += 1;

	if (tree) {
		proto_tree_add_item(isis_tree, hf_isis_version2, tvb, offset, 1,
			FALSE );
	}
	offset += 1;

	if (tree) {
		proto_tree_add_item(isis_tree, hf_isis_reserved, tvb, offset, 1,
			FALSE );
	}
	offset += 1;

	if (tree) {
		proto_tree_add_item(isis_tree, hf_isis_max_area_adr, tvb, offset, 1,
			FALSE );
	}
	offset += 1;

	/*
	 * Interpret the system ID length.
	 */
	if (isis_system_id_len == 0)
		isis_system_id_len = 6;	/* zero means 6-octet ID field length */
	else if (isis_system_id_len == 255) {
		isis_system_id_len = 0;	/* 255 means null ID field */
		/* XXX - what about the LAN ID? */
	}
	/* XXX - otherwise, must be in the range 1 through 8 */

	switch (isis_type) {
	case ISIS_TYPE_L1_HELLO:
	case ISIS_TYPE_L2_HELLO:
	case ISIS_TYPE_PTP_HELLO:
		isis_dissect_isis_hello(tvb, pinfo, isis_tree, offset,
			isis_type, isis_header_length, isis_system_id_len);
		break;
	case ISIS_TYPE_L1_LSP:
	case ISIS_TYPE_L2_LSP:
		isis_dissect_isis_lsp(tvb, pinfo, isis_tree, offset,
			isis_type, isis_header_length, isis_system_id_len);
		break;
	case ISIS_TYPE_L1_CSNP:
	case ISIS_TYPE_L2_CSNP:
		isis_dissect_isis_csnp(tvb, pinfo, isis_tree, offset,
			isis_type, isis_header_length, isis_system_id_len);
		break;
	case ISIS_TYPE_L1_PSNP:
	case ISIS_TYPE_L2_PSNP:
		isis_dissect_isis_psnp(tvb, pinfo, isis_tree, offset,
			isis_type, isis_header_length, isis_system_id_len);
		break;
	default:
		isis_dissect_unknown(tvb, tree, offset,
			"Unknown ISIS packet type");
	}
} /* dissect_isis */
static void
dissect_sap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	int offset = 0;
        int sap_version, is_ipv6, is_del, is_enc, is_comp, addr_len;
        guint8 vers_flags;
        guint8 auth_len;
        guint16 tmp1;
        guint8 auth_flags;
        tvbuff_t *next_tvb;

        proto_item *si, *sif;
        proto_tree *sap_tree, *sap_flags_tree;

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

	vers_flags = tvb_get_guint8(tvb, offset);
        is_ipv6 = vers_flags&MCAST_SAP_BIT_A;
        is_del = vers_flags&MCAST_SAP_BIT_T;
        is_enc = vers_flags&MCAST_SAP_BIT_E;
        is_comp = vers_flags&MCAST_SAP_BIT_C;

        sap_version = (vers_flags&MCAST_SAP_VERSION_MASK)>>MCAST_SAP_VERSION_SHIFT;
        addr_len = (is_ipv6) ? (int)sizeof(struct e_in6_addr) : 4;

        col_add_fstr(pinfo->cinfo, COL_INFO, "%s (v%u)",
                             (is_del) ? "Deletion" : "Announcement", sap_version);

	if (tree) {
	  si = proto_tree_add_item(tree, proto_sap, tvb, offset, -1, ENC_NA);
	  sap_tree = proto_item_add_subtree(si, ett_sap);

	  sif = proto_tree_add_uint(sap_tree, hf_sap_flags, tvb, offset, 1, vers_flags);
          sap_flags_tree = proto_item_add_subtree(sif, ett_sap_flags);
          proto_tree_add_uint(sap_flags_tree, hf_sap_flags_v, tvb, offset, 1, vers_flags);
          proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_a, tvb, offset, 1, vers_flags);
          proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_r, tvb, offset, 1, vers_flags);
          proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_t, tvb, offset, 1, vers_flags);
          proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_e, tvb, offset, 1, vers_flags);
          proto_tree_add_boolean(sap_flags_tree, hf_sap_flags_c, tvb, offset, 1, vers_flags);
          offset++;

          auth_len = tvb_get_guint8(tvb, offset);
          proto_tree_add_text(sap_tree, tvb, offset, 1, "Authentication Length: %u", auth_len);
          offset++;

          tmp1 = tvb_get_ntohs(tvb, offset);
          proto_tree_add_text(sap_tree, tvb, offset, 2, "Message Identifier Hash: 0x%x", tmp1);
          offset +=2;

          proto_tree_add_text(sap_tree, tvb, offset, addr_len, "Originating Source: %s",
              (is_ipv6) ? tvb_ip6_to_str(tvb, offset) : tvb_ip_to_str(tvb, offset));
          offset += addr_len;

          /* Authentication data lives in its own subtree */
          if (auth_len > 0) {
                  guint32 auth_data_len;
                  proto_item *sdi, *sai;
                  proto_tree *sa_tree, *saf_tree;
                  int has_pad;
                  guint8 pad_len = 0;

                  auth_data_len = (guint32)(auth_len * sizeof(guint32));

                  sdi = proto_tree_add_item(sap_tree, hf_auth_data, tvb, offset, auth_data_len, ENC_NA);
                  sa_tree = proto_item_add_subtree(sdi, ett_sap_auth);

                  auth_flags = tvb_get_guint8(tvb, offset);
                  sai = proto_tree_add_uint(sa_tree, hf_auth_flags, tvb, offset, 1, auth_flags);
                  saf_tree = proto_item_add_subtree(sai, ett_sap_authf);
                  proto_tree_add_uint(saf_tree, hf_auth_flags_v, tvb, offset, 1, auth_flags);
                  proto_tree_add_boolean(saf_tree, hf_auth_flags_p, tvb, offset, 1, auth_flags);
                  proto_tree_add_uint(saf_tree, hf_auth_flags_t, tvb, offset, 1, auth_flags);

                  has_pad = auth_flags&MCAST_SAP_AUTH_BIT_P;
                  if (has_pad)
			  pad_len = tvb_get_guint8(tvb, offset+auth_data_len-1);

		  if ((int) auth_data_len - pad_len - 1 < 0) {
        		  proto_tree_add_text(sa_tree, tvb, 0, 0,
                        		      "Bogus authentication length (%d) or pad length (%d)",
                        		      auth_len, pad_len);
        		  return;
		  }


                  proto_tree_add_text(sa_tree, tvb, offset+1, auth_data_len-pad_len-1,
                                      "Authentication subheader: (%u byte%s)",
                                      auth_data_len-1, plurality(auth_data_len-1, "", "s"));
                  if (has_pad) {
                          proto_tree_add_text(sa_tree, tvb, offset+auth_data_len-pad_len, pad_len,
                                              "Authentication data padding: (%u byte%s)",
                                              pad_len, plurality(pad_len, "", "s"));
                          proto_tree_add_text(sa_tree, tvb, offset+auth_data_len-1, 1,
                                              "Authentication data pad count: %u byte%s",
                                              pad_len, plurality(pad_len, "", "s"));
                  }

                  offset += auth_data_len;
          }
          if (is_enc || is_comp) {
                  const char *mangle;
                  if (is_enc && is_comp) mangle = "compressed and encrypted";
                  else if (is_enc) mangle = "encrypted";
                  else mangle = "compressed";
                  proto_tree_add_text(sap_tree, tvb, offset, -1,
                                      "The rest of the packet is %s", mangle);
                  return;
          }

          /* Do we have the optional payload type aka. MIME content specifier */
          if (tvb_strneql(tvb, offset, "v=", strlen("v="))) {
                  gint remaining_len;
                  guint32 pt_len;
                  int pt_string_len;

                  remaining_len = tvb_length_remaining(tvb, offset);
                  if (remaining_len == 0) {
                      /*
                       * "tvb_strneql()" failed because there was no
		       * data left in the packet.
		       *
		       * Set the remaining length to 1, so that
		       * we throw the appropriate exception in
		       * "tvb_get_ptr()", rather than displaying
		       * the payload type.
		       */
		      remaining_len = 1;
		  }
                  pt_string_len = tvb_strnlen(tvb, offset, remaining_len);
                  if (pt_string_len == -1) {
                      /*
                       * We didn't find a terminating '\0'; run to the
                       * end of the buffer.
                       */
                      pt_string_len = remaining_len;
                      pt_len = pt_string_len;
                  } else {
                      /*
                       * Include the '\0' in the total item length.
                       */
                      pt_len = pt_string_len + 1;
                  }
                  proto_tree_add_text(sap_tree, tvb, offset, pt_len,
                      "Payload type: %.*s", pt_string_len,
                      tvb_get_ephemeral_string(tvb, offset, pt_string_len));
                  offset += pt_len;
          }
	}

        /* Done with SAP */
        next_tvb = tvb_new_subset_remaining(tvb, offset);
        call_dissector(sdp_handle, next_tvb, pinfo, tree);

        return;
}
Exemple #5
0
/*
 * Dissect TPKT-encapsulated data in a TCP stream.
 */
void
dissect_tpkt_encap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
		   gboolean desegment, dissector_handle_t subdissector_handle)
{
	proto_item *ti = NULL;
	proto_tree *tpkt_tree = NULL;
	volatile int offset = 0;
	int length_remaining;
	int data_len;
	volatile int length;
	tvbuff_t *volatile next_tvb;
	const char *saved_proto;
	void *pd_save;

	/*
	 * If we're reassembling segmented TPKT PDUs, empty the COL_INFO
	 * column, so subdissectors can append information
	 * without having to worry about emptying the column.
	 *
	 * We use "col_add_str()" because the subdissector
	 * might be appending information to the column, in
	 * which case we'd have to zero the buffer out explicitly
	 * anyway.
	 */
	if (desegment)
		col_set_str(pinfo->cinfo, COL_INFO, "");

	while (tvb_reported_length_remaining(tvb, offset) != 0) {
		/*
		 * Is the first byte of this putative TPKT header
		 * a valid TPKT version number, i.e. 3?
		 */
		if (tvb_get_guint8(tvb, offset) != 3) {
			/*
			 * No, so don't assume this is a TPKT header;
			 * we might be in the middle of TPKT data,
			 * so don't get the length and don't try to
			 * do reassembly.
			 */
			col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
			col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
			if (tree) {
				ti = proto_tree_add_item(tree, proto_tpkt, tvb,
				    offset, -1, ENC_NA);
				tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
				proto_item_set_text(ti, "TPKT");

				proto_tree_add_text(tpkt_tree, tvb, offset, -1,
				    "Continuation data");
			}
			return;
		}

		length_remaining = tvb_length_remaining(tvb, offset);

		/*
		 * Can we do reassembly?
		 */
		if (desegment && pinfo->can_desegment) {
			/*
			 * Yes - is the TPKT header split across segment
			 * boundaries?
			 */
			if (length_remaining < 4) {
				/*
				 * Yes.  Tell the TCP dissector where the data
				 * for this message starts in the data it
				 * handed us and that we need "some more data."
				 * Don't tell it exactly how many bytes we need
				 * because if/when we ask for even more (after
				 * the header) that will break reassembly.
				 */
				pinfo->desegment_offset = offset;
				pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
				return;
			}
		}

		/*
		 * Get the length from the TPKT header.
		 */
		data_len = tvb_get_ntohs(tvb, offset + 2);

		/*
		 * Can we do reassembly?
		 */
		if (desegment && pinfo->can_desegment) {
			/*
			 * Yes - is the payload split across segment
			 * boundaries?
			 */
			if (length_remaining < data_len) {
				/*
				 * Yes.  Tell the TCP dissector where
				 * the data for this message starts in
				 * the data it handed us, and how many
				 * more bytes we need, and return.
				 */
				pinfo->desegment_offset = offset;
				pinfo->desegment_len =
				    data_len - length_remaining;
				return;
			}
		}

		/*
		 * Dissect the TPKT header.
		 * Save and restore "pinfo->current_proto".
		 */
		saved_proto = pinfo->current_proto;
		pinfo->current_proto = "TPKT";

		col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
		/*
		 * Don't add the TPKT header information if we're
		 * reassembling segmented TPKT PDUs or if this
		 * PDU isn't reassembled.
		 *
		 * XXX - the first is so that subdissectors can append
		 * information without getting TPKT stuff in the middle;
		 * why the second?
		 */
		if (!desegment && !pinfo->fragmented) {
			col_add_fstr(pinfo->cinfo, COL_INFO,
			    "TPKT Data length = %u", data_len);
		}

		if (tree) {
			ti = proto_tree_add_item(tree, proto_tpkt, tvb,
			    offset, 4, ENC_NA);
			tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
			proto_item_set_text(ti, "TPKT");

			/* Version */
			proto_tree_add_item(tpkt_tree, hf_tpkt_version, tvb,
			    offset, 1, ENC_BIG_ENDIAN);
			proto_item_append_text(ti, ", Version: 3");

			/* Reserved octet*/
			proto_tree_add_item(tpkt_tree, hf_tpkt_reserved, tvb,
			    offset + 1, 1, ENC_BIG_ENDIAN);

			/* Length */
			proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb,
			    offset + 2, 2, data_len);
			proto_item_append_text(ti, ", Length: %u", data_len);
		}
		pinfo->current_proto = saved_proto;

		/* Skip the TPKT header. */
		offset += 4;
		data_len -= 4;

		/*
		 * Construct a tvbuff containing the amount of the payload
		 * we have available.  Make its reported length the
		 * amount of data in this TPKT packet.
		 *
		 * XXX - if reassembly isn't enabled. the subdissector
		 * will throw a BoundsError exception, rather than a
		 * ReportedBoundsError exception.  We really want
		 * a tvbuff where the length is "length", the reported
		 * length is "plen + 2", and the "if the snapshot length
		 * were infinite" length were the minimum of the
		 * reported length of the tvbuff handed to us and "plen+2",
		 * with a new type of exception thrown if the offset is
		 * within the reported length but beyond that third length,
		 * with that exception getting the "Unreassembled Packet"
		 * error.
		 */
		length = length_remaining - 4;
		if (length > data_len)
			length = data_len;
		next_tvb = tvb_new_subset(tvb, offset, length, data_len);

		/*
		 * Call the subdissector.
		 *
		 * If it gets an error that means there's no point in
		 * dissecting any more TPKT messages, rethrow the
		 * exception in question.
		 *
		 * If it gets any other error, report it and continue,
		 * as that means that TPKT message got an error, but
		 * that doesn't mean we should stop dissecting TPKT
		 * messages within this frame or chunk of reassembled
		 * data.
		 */
		pd_save = pinfo->private_data;
		TRY {
			call_dissector(subdissector_handle, next_tvb, pinfo,
			    tree);
		}
		CATCH_NONFATAL_ERRORS {
			/*  Restore the private_data structure in case one of the
			 *  called dissectors modified it (and, due to the exception,
			 *  was unable to restore it).
			 */
			pinfo->private_data = pd_save;

			show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
		}
		ENDTRY;

		/*
		 * Skip the payload.
		 */
		offset += length;
	}
}
void
dissect_sss_request(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, ncp_req_hash_value *request_value)
{
    guint8              /*func,*/ subfunc = 0;
    guint32             subverb=0;
    guint32             msg_length=0;
    guint32             foffset= 0;
    proto_tree          *atree;
    proto_item          *aitem;


    if (tvb_length_remaining(tvb, foffset)<4) {
        return;
    }
    foffset = 6;
    /*func = tvb_get_guint8(tvb, foffset);*/
    foffset += 1;
    subfunc = tvb_get_guint8(tvb, foffset);
    foffset += 1;

    /* Fill in the PROTOCOL & INFO  columns. */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "NSSS");
    col_add_fstr(pinfo->cinfo, COL_INFO, "C SecretStore - %s", val_to_str(subfunc, sss_func_enum, "Unknown (%d)"));

    switch (subfunc) {
    case 1:
        aitem = proto_tree_add_text(ncp_tree, tvb, foffset, tvb_length_remaining(tvb, foffset), "Packet Type: %s", val_to_str(subfunc, sss_func_enum, "Unknown (%d)"));
        atree = proto_item_add_subtree(aitem, ett_sss);
        proto_tree_add_item(atree, hf_ping_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        foffset += 4;
        proto_tree_add_item(atree, hf_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        foffset += 4;
        break;
    case 2:
        proto_tree_add_item(ncp_tree, hf_frag_handle, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        if (tvb_get_letohl(tvb, foffset)==0xffffffff) /* Fragment handle of -1 means no fragment. So process packet */
        {
            foffset += 4;
            proto_tree_add_item(ncp_tree, hf_buffer_size, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
            foffset += 4;
            proto_tree_add_item(ncp_tree, hf_length, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
            foffset += 4;
            foffset += 12; /* Blank Context */
            subverb = tvb_get_letohl(tvb, foffset);
            col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", val_to_str(subverb, sss_verb_enum, "Unknown (%d)"));

            aitem = proto_tree_add_item(ncp_tree, hf_verb, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
            atree = proto_item_add_subtree(aitem, ett_sss);
            if (request_value) {
                request_value->req_nds_flags=subverb;
            }
            foffset += 4;
            process_flags(atree, tvb, foffset);
            foffset += 4;
            proto_tree_add_item(atree, hf_context, tvb, foffset, 4, ENC_BIG_ENDIAN);
            foffset += 4;
            switch (subverb) {
            case 0:
                foffset += 4;
                foffset = sss_string(tvb, hf_user, atree, foffset, TRUE, 0);
                break;
            case 1:
                foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0);
                msg_length = tvb_get_letohl(tvb, foffset);
                foffset += (msg_length+4);   /* Unsure of what this length and parameter are */
                /* A bad secret of length greater then 256 characters will cause frag
                   packets and then we will see these as malformed packets.
                   So check to make sure we still have data in the packet anytime
                   we read a secret. */
                if (tvb_length_remaining(tvb, foffset) > 4)
                {
                    foffset = sss_string(tvb, hf_user, atree, foffset, TRUE, 0);
                }
                break;
            case 2:
                foffset += 4;
                foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0);
                if (tvb_length_remaining(tvb, foffset) > 4)
                {
                    msg_length = tvb_get_letohl(tvb, foffset);
                    foffset += 4;
                    if (tvb_length_remaining(tvb, foffset) < (gint) msg_length)
                    {
                        proto_tree_add_item(atree, hf_enc_data, tvb, foffset, -1, ENC_NA);
                    }
                    else
                    {
                        proto_tree_add_item(atree, hf_enc_data, tvb, foffset, msg_length, ENC_NA);
                    }
                }
                break;
            case 3:
            case 4:
                foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0);
                if (tvb_length_remaining(tvb, foffset) > 4)
                {
                    foffset = sss_string(tvb, hf_user, atree, foffset, TRUE, 0);
                }
                break;
            case 5:
                break;
            case 6:
                foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, 0);
                if (tvb_length_remaining(tvb, foffset) > 4)
                {
                    foffset = sss_string(tvb, hf_user, atree, foffset, TRUE, 0);
                }
                break;
            case 7:
                msg_length = tvb_get_letohl(tvb, foffset);
                foffset += 4;
                proto_tree_add_item(atree, hf_enc_cred, tvb, foffset, msg_length, ENC_NA);
                break;
            case 8:
            case 9:
            default:
                break;
            }

        }
        else
        {
            col_set_str(pinfo->cinfo, COL_INFO, "C SecretStore - fragment");
            proto_tree_add_text(ncp_tree, tvb, foffset, 4, "Fragment");

            /* Fragments don't really carry a subverb so store 0xff as the subverb number */
            if (request_value) {
                request_value->req_nds_flags=255;
            }
            if (tvb_length_remaining(tvb, foffset) > 8)
            {
                foffset += 4;
                proto_tree_add_item(ncp_tree, hf_enc_data, tvb, foffset, tvb_length_remaining(tvb, foffset), ENC_NA);
            }
        }
        break;
    case 3:
        /* No Op */
        break;
    default:
        break;
    }
}
Exemple #7
0
/* Code to actually dissect the packets */
static void
dissect_rngrsp (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
{
  proto_item *it;
  proto_tree *rngrsp_tree;
  guint8 tlvtype, tlvlen;
  int pos;
  gint length;
  guint8 upchid;
  guint16 sid;
  gint8 pwr;
  gint32 tim;

  sid = tvb_get_ntohs (tvb, 0);
  upchid = tvb_get_guint8 (tvb, 2);

  if (upchid > 0)
	col_add_fstr (pinfo->cinfo, COL_INFO,
		      "Ranging Response: SID = %u, Upstream Channel = %u (U%u)",
		      sid, upchid, upchid - 1);
  else
	col_add_fstr (pinfo->cinfo, COL_INFO,
		      "Ranging Response: SID = %u, Telephony Return", sid);


  if (tree)
    {
      it =
	proto_tree_add_protocol_format (tree, proto_docsis_rngrsp, tvb, 0, -1,
					"Ranging Response");
      rngrsp_tree = proto_item_add_subtree (it, ett_docsis_rngrsp);
      proto_tree_add_item (rngrsp_tree, hf_docsis_rngrsp_sid, tvb, 0, 2,
			   ENC_BIG_ENDIAN);
      proto_tree_add_item (rngrsp_tree, hf_docsis_rngrsp_upstream_chid, tvb,
			   2, 1, ENC_BIG_ENDIAN);

      length = tvb_reported_length_remaining (tvb, 0);
      pos = 3;
      while (pos < length)
	{
	  tlvtype = tvb_get_guint8 (tvb, pos++);
	  tlvlen = tvb_get_guint8 (tvb, pos++);
	  switch (tlvtype)
	    {
	    case RNGRSP_TIMING:
	      if (tlvlen == 4)
		{
		  tim = tvb_get_ntohl (tvb, pos);
		  proto_tree_add_int (rngrsp_tree,
				      hf_docsis_rngrsp_timing_adj, tvb, pos,
				      tlvlen, tim);
		}
	      else
		{
		  THROW (ReportedBoundsError);
		}
	      break;
	    case RNGRSP_PWR_LEVEL_ADJ:
	      if (tlvlen == 1)
		{
		  pwr = tvb_get_guint8 (tvb, pos);
		  proto_tree_add_int (rngrsp_tree, hf_docsis_rngrsp_power_adj,
				      tvb, pos, tlvlen, pwr);
		}
	      else
		{
		  THROW (ReportedBoundsError);
		}
	      break;
	    case RNGRSP_OFFSET_FREQ_ADJ:
	      if (tlvlen == 2)
		{
		  proto_tree_add_item (rngrsp_tree, hf_docsis_rngrsp_freq_adj,
				       tvb, pos, tlvlen, ENC_BIG_ENDIAN);
		}
	      else
		{
		  THROW (ReportedBoundsError);
		}
	      break;
	    case RNGRSP_TRANSMIT_EQ_ADJ:
	      proto_tree_add_item (rngrsp_tree, hf_docsis_rngrsp_xmit_eq_adj,
				   tvb, pos, tlvlen, ENC_NA);
	      break;
	    case RNGRSP_RANGING_STATUS:
	      if (tlvlen == 1)
		proto_tree_add_item (rngrsp_tree,
				     hf_docsis_rngrsp_ranging_status, tvb,
				     pos, tlvlen, ENC_BIG_ENDIAN);
	      else
		{
		  THROW (ReportedBoundsError);
		}
	      break;
	    case RNGRSP_DOWN_FREQ_OVER:
	      if (tlvlen == 4)
		proto_tree_add_item (rngrsp_tree,
				     hf_docsis_rngrsp_down_freq_over, tvb,
				     pos, tlvlen, ENC_BIG_ENDIAN);
	      else
		{
		  THROW (ReportedBoundsError);
		}
	      break;
	    case RNGRSP_UP_CHID_OVER:
	      if (tlvlen == 1)
		proto_tree_add_item (rngrsp_tree,
				     hf_docsis_rngrsp_upstream_ch_over, tvb,
				     pos, tlvlen, ENC_BIG_ENDIAN);
	      else
		{
		  THROW (ReportedBoundsError);
		}
	      break;

	    }			/* switch(tlvtype) */
	  pos = pos + tlvlen;
	}			/* while (pos < length) */
    }				/* if (tree) */
}
Exemple #8
0
static int
dissect_frame(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
{
	proto_item  *volatile ti = NULL, *comment_item;
	guint	     cap_len = 0, frame_len = 0;
	proto_tree  *volatile tree;
	proto_tree  *comments_tree;
	proto_tree  *volatile fh_tree = NULL;
	proto_item  *item;
	const gchar *cap_plurality, *frame_plurality;
	frame_data_t *fr_data = (frame_data_t*)data;
	const color_filter_t *color_filter;

	tree=parent_tree;

	switch (pinfo->phdr->rec_type) {

	case REC_TYPE_PACKET:
		pinfo->current_proto = "Frame";
		if (pinfo->pseudo_header != NULL) {
			switch (pinfo->pkt_encap) {

			case WTAP_ENCAP_WFLEET_HDLC:
			case WTAP_ENCAP_CHDLC_WITH_PHDR:
			case WTAP_ENCAP_PPP_WITH_PHDR:
			case WTAP_ENCAP_SDLC:
			case WTAP_ENCAP_BLUETOOTH_H4_WITH_PHDR:
				pinfo->p2p_dir = pinfo->pseudo_header->p2p.sent ?
				    P2P_DIR_SENT : P2P_DIR_RECV;
				break;

			case WTAP_ENCAP_BLUETOOTH_HCI:
				pinfo->p2p_dir = pinfo->pseudo_header->bthci.sent;
				break;

			case WTAP_ENCAP_LAPB:
			case WTAP_ENCAP_FRELAY_WITH_PHDR:
				pinfo->p2p_dir =
				    (pinfo->pseudo_header->x25.flags & FROM_DCE) ?
				    P2P_DIR_RECV : P2P_DIR_SENT;
				break;

			case WTAP_ENCAP_ISDN:
			case WTAP_ENCAP_V5_EF:
			case WTAP_ENCAP_DPNSS:
			case WTAP_ENCAP_BACNET_MS_TP_WITH_PHDR:
				pinfo->p2p_dir = pinfo->pseudo_header->isdn.uton ?
				    P2P_DIR_SENT : P2P_DIR_RECV;
				break;

			case WTAP_ENCAP_LINUX_LAPD:
				pinfo->p2p_dir = (pinfo->pseudo_header->lapd.pkttype == 3 ||
					pinfo->pseudo_header->lapd.pkttype == 4) ?
					P2P_DIR_SENT : P2P_DIR_RECV;
				break;

			case WTAP_ENCAP_MTP2_WITH_PHDR:
				pinfo->p2p_dir = pinfo->pseudo_header->mtp2.sent ?
				    P2P_DIR_SENT : P2P_DIR_RECV;
				pinfo->link_number  = pinfo->pseudo_header->mtp2.link_number;
				break;

			case WTAP_ENCAP_GSM_UM:
				pinfo->p2p_dir = pinfo->pseudo_header->gsm_um.uplink ?
				    P2P_DIR_SENT : P2P_DIR_RECV;
				break;
			}
		}
		break;

	case REC_TYPE_FT_SPECIFIC_EVENT:
		pinfo->current_proto = "Event";
		break;

	case REC_TYPE_FT_SPECIFIC_REPORT:
		pinfo->current_proto = "Report";
		break;

	default:
		g_assert_not_reached();
		break;
	}

	if (fr_data && fr_data->pkt_comment) {
		item = proto_tree_add_item(tree, proto_pkt_comment, tvb, 0, 0, ENC_NA);
		comments_tree = proto_item_add_subtree(item, ett_comments);
		comment_item = proto_tree_add_string_format(comments_tree, hf_comments_text, tvb, 0, 0,
							                   fr_data->pkt_comment, "%s",
							                   fr_data->pkt_comment);
		expert_add_info_format(pinfo, comment_item, &ei_comments_text,
					                       "%s",  fr_data->pkt_comment);


	}

	/* if FRAME is not referenced from any filters we don't need to worry about
	   generating any tree items.  */
	if (!proto_field_is_referenced(tree, proto_frame)) {
		tree=NULL;
		if (pinfo->presence_flags & PINFO_HAS_TS) {
			if (pinfo->abs_ts.nsecs < 0 || pinfo->abs_ts.nsecs >= 1000000000)
				expert_add_info(pinfo, NULL, &ei_arrive_time_out_of_range);
		}
	} else {
		gboolean old_visible;

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

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

		ti = proto_tree_add_protocol_format(tree, proto_frame, tvb, 0, tvb_captured_length(tvb),
		    "Frame %u: %u byte%s on wire",
		    pinfo->num, frame_len, frame_plurality);
		if (generate_bits_field)
			proto_item_append_text(ti, " (%u bits)", frame_len * 8);
		proto_item_append_text(ti, ", %u byte%s captured",
		    cap_len, cap_plurality);
		if (generate_bits_field) {
			proto_item_append_text(ti, " (%u bits)",
			    cap_len * 8);
		}
		if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID) {
			proto_item_append_text(ti, " on interface %u",
			    pinfo->phdr->interface_id);
		}
		if (pinfo->phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
			if (pinfo->phdr->pack_flags & 0x00000001) {
				proto_item_append_text(ti, " (inbound)");
				pinfo->p2p_dir = P2P_DIR_RECV;
			}
			if (pinfo->phdr->pack_flags & 0x00000002) {
				proto_item_append_text(ti, " (outbound)");
				pinfo->p2p_dir = P2P_DIR_SENT;
			}
		}

		fh_tree = proto_item_add_subtree(ti, ett_frame);

		if (pinfo->phdr->presence_flags & WTAP_HAS_INTERFACE_ID && proto_field_is_referenced(tree, hf_frame_interface_id)) {
			const char *interface_name = epan_get_interface_name(pinfo->epan, pinfo->phdr->interface_id);

			if (interface_name)
				proto_tree_add_uint_format_value(fh_tree, hf_frame_interface_id, tvb, 0, 0, pinfo->phdr->interface_id, "%u (%s)", pinfo->phdr->interface_id, interface_name);
			else
				proto_tree_add_uint(fh_tree, hf_frame_interface_id, tvb, 0, 0, pinfo->phdr->interface_id);
		}

		if (pinfo->phdr->presence_flags & WTAP_HAS_PACK_FLAGS) {
			proto_tree *flags_tree;
			proto_item *flags_item;

			flags_item = proto_tree_add_uint(fh_tree, hf_frame_pack_flags, tvb, 0, 0, pinfo->phdr->pack_flags);
			flags_tree = proto_item_add_subtree(flags_item, ett_flags);
			proto_tree_add_uint(flags_tree, hf_frame_pack_direction, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_uint(flags_tree, hf_frame_pack_reception_type, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_uint(flags_tree, hf_frame_pack_fcs_length, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_uint(flags_tree, hf_frame_pack_reserved, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_crc_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_packet_too_long_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_packet_too_short_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_wrong_inter_frame_gap_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_unaligned_frame_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_start_frame_delimiter_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_preamble_error, tvb, 0, 0, pinfo->phdr->pack_flags);
			proto_tree_add_boolean(flags_tree, hf_frame_pack_symbol_error, tvb, 0, 0, pinfo->phdr->pack_flags);
		}

		if (pinfo->phdr->rec_type == REC_TYPE_PACKET)
			proto_tree_add_int(fh_tree, hf_frame_wtap_encap, tvb, 0, 0, pinfo->pkt_encap);

		if (pinfo->presence_flags & PINFO_HAS_TS) {
			proto_tree_add_time(fh_tree, hf_frame_arrival_time, tvb,
					    0, 0, &(pinfo->abs_ts));
			if (pinfo->abs_ts.nsecs < 0 || pinfo->abs_ts.nsecs >= 1000000000) {
				expert_add_info_format(pinfo, ti, &ei_arrive_time_out_of_range,
								  "Arrival Time: Fractional second %09ld is invalid,"
								  " the valid range is 0-1000000000",
								  (long) pinfo->abs_ts.nsecs);
			}
			item = proto_tree_add_time(fh_tree, hf_frame_shift_offset, tvb,
					    0, 0, &(pinfo->fd->shift_offset));
			PROTO_ITEM_SET_GENERATED(item);

			if (generate_epoch_time) {
				proto_tree_add_time(fh_tree, hf_frame_arrival_time_epoch, tvb,
						    0, 0, &(pinfo->abs_ts));
			}

			if (proto_field_is_referenced(tree, hf_frame_time_delta)) {
				nstime_t     del_cap_ts;

				frame_delta_abs_time(pinfo->epan, pinfo->fd, pinfo->num - 1, &del_cap_ts);

				item = proto_tree_add_time(fh_tree, hf_frame_time_delta, tvb,
							   0, 0, &(del_cap_ts));
				PROTO_ITEM_SET_GENERATED(item);
			}

			if (proto_field_is_referenced(tree, hf_frame_time_delta_displayed)) {
				nstime_t del_dis_ts;

				frame_delta_abs_time(pinfo->epan, pinfo->fd, pinfo->fd->prev_dis_num, &del_dis_ts);

				item = proto_tree_add_time(fh_tree, hf_frame_time_delta_displayed, tvb,
							   0, 0, &(del_dis_ts));
				PROTO_ITEM_SET_GENERATED(item);
			}

			item = proto_tree_add_time(fh_tree, hf_frame_time_relative, tvb,
						   0, 0, &(pinfo->rel_ts));
			PROTO_ITEM_SET_GENERATED(item);

			if (pinfo->fd->flags.ref_time) {
				ti = proto_tree_add_item(fh_tree, hf_frame_time_reference, tvb, 0, 0, ENC_NA);
				PROTO_ITEM_SET_GENERATED(ti);
			}
		}

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

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

		proto_tree_add_uint_format(fh_tree, hf_frame_capture_len, tvb,
					   0, 0, cap_len, "Capture Length: %u byte%s (%u bits)",
					   cap_len, cap_plurality, cap_len * 8);

		if (generate_md5_hash) {
			const guint8 *cp;
			md5_state_t   md_ctx;
			md5_byte_t    digest[16];
			const gchar  *digest_string;

			cp = tvb_get_ptr(tvb, 0, cap_len);

			md5_init(&md_ctx);
			md5_append(&md_ctx, cp, cap_len);
			md5_finish(&md_ctx, digest);

			digest_string = bytestring_to_str(wmem_packet_scope(), digest, 16, '\0');
			ti = proto_tree_add_string(fh_tree, hf_frame_md5_hash, tvb, 0, 0, digest_string);
			PROTO_ITEM_SET_GENERATED(ti);
		}

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

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

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

		/* Check for existences of P2P pseudo header */
		if (pinfo->p2p_dir != P2P_DIR_UNKNOWN) {
			proto_tree_add_int(fh_tree, hf_frame_p2p_dir, tvb,
					   0, 0, pinfo->p2p_dir);
		}

		/* Check for existences of MTP2 link number */
		if ((pinfo->pseudo_header != NULL ) && (pinfo->pkt_encap == WTAP_ENCAP_MTP2_WITH_PHDR)) {
			proto_tree_add_uint(fh_tree, hf_link_number, tvb,
					    0, 0, pinfo->link_number);
		}

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

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

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

			case REC_TYPE_PACKET:
				if ((force_docsis_encap) && (docsis_handle)) {
					call_dissector_with_data(docsis_handle,
					    tvb, pinfo, parent_tree,
					    (void *)pinfo->pseudo_header);
				} else {
					if (!dissector_try_uint_new(wtap_encap_dissector_table,
					    pinfo->pkt_encap, tvb, pinfo,
					    parent_tree, TRUE,
					    (void *)pinfo->pseudo_header)) {
						col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
						col_add_fstr(pinfo->cinfo, COL_INFO, "WTAP_ENCAP = %d",
							     pinfo->pkt_encap);
						call_dissector_with_data(data_handle,
						    tvb, pinfo, parent_tree,
						    (void *)pinfo->pseudo_header);
					}
				}
				break;

			case REC_TYPE_FT_SPECIFIC_EVENT:
			case REC_TYPE_FT_SPECIFIC_REPORT:
				{
					int file_type_subtype = WTAP_FILE_TYPE_SUBTYPE_UNKNOWN;

					if (fr_data) {
						file_type_subtype = fr_data->file_type_subtype;
					}

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

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

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

	/* Attempt to (re-)calculate color filters (if any). */
	if (pinfo->fd->flags.need_colorize) {
		color_filter = color_filters_colorize_packet(fr_data->color_edt);
		pinfo->fd->color_filter = color_filter;
		pinfo->fd->flags.need_colorize = 0;
	} else {
		color_filter = pinfo->fd->color_filter;
	}
	if (color_filter) {
		item = proto_tree_add_string(fh_tree, hf_frame_color_filter_name, tvb,
					     0, 0, color_filter->filter_name);
		PROTO_ITEM_SET_GENERATED(item);
		item = proto_tree_add_string(fh_tree, hf_frame_color_filter_text, tvb,
					     0, 0, color_filter->filter_text);
		PROTO_ITEM_SET_GENERATED(item);
	}

	tap_queue_packet(frame_tap, pinfo, NULL);


	if (pinfo->frame_end_routines) {
		g_slist_foreach(pinfo->frame_end_routines, &call_frame_end_routine, NULL);
		g_slist_free(pinfo->frame_end_routines);
		pinfo->frame_end_routines = NULL;
	}

	if (prefs.enable_incomplete_dissectors_check && tree && tree->tree_data->visible) {
		gchar* decoded;
		guint length;
		guint i;
		guint byte;
		guint bit;

		length = tvb_captured_length(tvb);
		decoded = proto_find_undecoded_data(tree, length);

		for (i = 0; i < length; i++) {
			byte = i / 8;
			bit = i % 8;
			if (!(decoded[byte] & (1 << bit))) {
				field_info* fi = proto_find_field_from_offset(tree, i, tvb);
				if (fi && fi->hfinfo->id != proto_frame) {
					g_log(LOG_DOMAIN_CAPTURE, G_LOG_LEVEL_WARNING,
						"Dissector %s incomplete in frame %u: undecoded byte number %u "
						"(0x%.4X+%u)",
						(fi ? fi->hfinfo->abbrev : "[unknown]"),
						pinfo->num, i, i - i % 16, i % 16);
					proto_tree_add_expert_format(tree, pinfo, &ei_incomplete, tvb, i, 1, "Undecoded byte number: %u (0x%.4X+%u)", i, i - i % 16, i % 16);
				}
			}
		}
        }

	return tvb_captured_length(tvb);
}
/*
 * dissect_pgm - The dissector for Pragmatic General Multicast
 */
static void
dissect_pgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint16 pgmhdr_sport;
	guint16 pgmhdr_dport;
	guint8 pgmhdr_type;
	guint8 pgmhdr_opts;
	guint16 pgmhdr_cksum;
	guint16 pgmhdr_tsdulen;
	guint32 sqn;
	guint16 afi;

	guint plen = 0;
	proto_item *ti;
	const char *pktname;
	const char *pollstname;
	char *gsi;
	gboolean isdata = FALSE;
	guint pgmlen, reportedlen;

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

	col_clear(pinfo->cinfo, COL_INFO);
	if (tvb_reported_length_remaining(tvb, 0) < 18) {
		col_set_str(pinfo->cinfo, COL_INFO,
				"Packet too small");
		return;
	}

	pinfo->srcport = pgmhdr_sport = tvb_get_ntohs(tvb, 0);
	pinfo->destport = pgmhdr_dport = tvb_get_ntohs(tvb, 2);

	pgmhdr_type = tvb_get_guint8(tvb, 4);
	pktname = val_to_str(pgmhdr_type, type_vals, "Unknown (0x%02x)");

	pgmhdr_opts = tvb_get_guint8(tvb, 5);
	pgmhdr_cksum = tvb_get_ntohs(tvb, 6);
	gsi = tvb_bytes_to_ep_str(tvb, 8, 6);
	pgmhdr_tsdulen = tvb_get_ntohs(tvb, 14);
	sqn = tvb_get_ntohl(tvb, 16);

	switch(pgmhdr_type) {
	case PGM_SPM_PCKT:
	case PGM_NAK_PCKT:
	case PGM_NNAK_PCKT:
	case PGM_NCF_PCKT:
	case PGM_POLR_PCKT:
	case PGM_ACK_PCKT:
		col_add_fstr(pinfo->cinfo, COL_INFO,
				"%-5s sqn 0x%x gsi %s", pktname, sqn, gsi);
		break;
	case PGM_RDATA_PCKT:
	case PGM_ODATA_PCKT:
		col_add_fstr(pinfo->cinfo, COL_INFO,
			    "%-5s sqn 0x%x gsi %s tsdulen %d", pktname, sqn, gsi,
			    pgmhdr_tsdulen);

		isdata = TRUE;
		break;
	case PGM_POLL_PCKT: {
		guint16 poll_stype = tvb_get_ntohs(tvb, 22);
		pollstname = val_to_str(poll_stype, poll_subtype_vals, "Unknown (0x%02x)");

		col_add_fstr(pinfo->cinfo, COL_INFO,
				"%-5s sqn 0x%x gsi %s subtype %s",
					pktname, sqn, gsi, pollstname);
		}
		break;
	default:
		return;
	}

	{
		proto_tree *pgm_tree = NULL;
		proto_tree *opt_tree = NULL;
		proto_tree *type_tree = NULL;
		proto_item *tf, *hidden_item;
		ptvcursor_t* cursor;

		ti = proto_tree_add_protocol_format(tree, proto_pgm,
			tvb, 0, -1,
			"Pragmatic General Multicast: Type %s"
			    " Src Port %u, Dst Port %u, GSI %s", pktname,
			pgmhdr_sport, pgmhdr_dport, gsi);

		pgm_tree = proto_item_add_subtree(ti, ett_pgm);

		cursor = ptvcursor_new(pgm_tree, tvb, 0);

		hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 0, 2, ENC_BIG_ENDIAN);
		PROTO_ITEM_SET_HIDDEN(hidden_item);
		hidden_item = proto_tree_add_item(pgm_tree, hf_pgm_port, tvb, 2, 2, ENC_BIG_ENDIAN);
		PROTO_ITEM_SET_HIDDEN(hidden_item);
		ptvcursor_add(cursor, hf_pgm_main_sport, 2, ENC_BIG_ENDIAN);
		ptvcursor_add(cursor, hf_pgm_main_dport, 2, ENC_BIG_ENDIAN);
		ptvcursor_add(cursor, hf_pgm_main_type, 1, ENC_BIG_ENDIAN);

		tf = proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_opts, tvb,
			ptvcursor_current_offset(cursor), 1, pgmhdr_opts, "%s (0x%x)",
			optsstr(pgmhdr_opts), pgmhdr_opts);
		opt_tree = proto_item_add_subtree(tf, ett_pgm_optbits);
		ptvcursor_set_tree(cursor, opt_tree);

		ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_opt, 1, ENC_BIG_ENDIAN);
		ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_netsig, 1, ENC_BIG_ENDIAN);
		ptvcursor_add_no_advance(cursor, hf_pgm_main_opts_varlen, 1, ENC_BIG_ENDIAN);
		ptvcursor_add(cursor, hf_pgm_main_opts_parity, 1, ENC_BIG_ENDIAN);
		ptvcursor_set_tree(cursor, pgm_tree);

		/* Checksum may be 0 (not available), but not for DATA packets */
		if ((pgmhdr_type != PGM_RDATA_PCKT) && (pgmhdr_type != PGM_ODATA_PCKT) &&
		    (pgmhdr_cksum == 0))
		{
			proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_cksum, tvb,
				ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "not available");
		} else {
			reportedlen = tvb_reported_length(tvb);
			pgmlen = tvb_length(tvb);
			if (pgm_check_checksum && pgmlen >= reportedlen) {
				vec_t cksum_vec[1];
				guint16 computed_cksum;

				cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pgmlen);
				cksum_vec[0].len = pgmlen;
				computed_cksum = in_cksum(&cksum_vec[0], 1);
				if (computed_cksum == 0) {
					proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_cksum, tvb,
						ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "0x%04x [correct]", pgmhdr_cksum);
				} else {
					hidden_item = proto_tree_add_boolean(pgm_tree, hf_pgm_main_cksum_bad, tvb,
					    ptvcursor_current_offset(cursor), 2, TRUE);
					PROTO_ITEM_SET_HIDDEN(hidden_item);
					proto_tree_add_uint_format_value(pgm_tree, hf_pgm_main_cksum, tvb,
					    ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "0x%04x [incorrect, should be 0x%04x]",
						pgmhdr_cksum, in_cksum_shouldbe(pgmhdr_cksum, computed_cksum));
				}
			} else {
				ptvcursor_add_no_advance(cursor, hf_pgm_main_cksum, 2, ENC_BIG_ENDIAN);
			}
		}
		ptvcursor_advance(cursor, 2);

		ptvcursor_add(cursor, hf_pgm_main_gsi, 6, ENC_NA);
		ptvcursor_add(cursor, hf_pgm_main_tsdulen, 2, ENC_BIG_ENDIAN);

		tf = proto_tree_add_text(pgm_tree, tvb, ptvcursor_current_offset(cursor), plen, "%s Packet", pktname);
		switch(pgmhdr_type) {
		case PGM_SPM_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_spm);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_spm_lead, 4, ENC_BIG_ENDIAN);
			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ti = ptvcursor_add(cursor, hf_pgm_spm_pathafi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_spm_res, 2, ENC_BIG_ENDIAN);

			switch (afi) {
			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_spm_path, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_spm_path6, 16, ENC_NA);
				break;

			default:
				expert_add_info(pinfo, ti, &ei_address_format_invalid);
				ptvcursor_free(cursor);
				return;
			}
			break;
		case PGM_RDATA_PCKT:
		case PGM_ODATA_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_data);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_spm_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_spm_trail, 4, ENC_BIG_ENDIAN);
			break;
		case PGM_NAK_PCKT:
		case PGM_NNAK_PCKT:
		case PGM_NCF_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_nak);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_nak_sqn, 4, ENC_BIG_ENDIAN);
			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ti = ptvcursor_add(cursor, hf_pgm_nak_srcafi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_nak_srcres, 2, ENC_BIG_ENDIAN);

			switch (afi) {
			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_nak_src, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_nak_src6, 16, ENC_NA);
				break;

			default:
				expert_add_info(pinfo, ti, &ei_address_format_invalid);
				break;
			}

			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ti = ptvcursor_add(cursor, hf_pgm_nak_grpafi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_nak_grpres, 2, ENC_BIG_ENDIAN);

			switch (afi) {
			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_nak_grp, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_nak_grp6, 16, ENC_NA);
				break;

			default:
				expert_add_info(pinfo, ti, &ei_address_format_invalid);
				ptvcursor_free(cursor);
				return;
			}
			break;
		case PGM_POLL_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_poll);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_poll_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_round, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_subtype, 2, ENC_BIG_ENDIAN);
			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ti = ptvcursor_add(cursor, hf_pgm_poll_pathafi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_res, 2, ENC_BIG_ENDIAN);

			switch (afi) {
			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_poll_path, 4, ENC_BIG_ENDIAN);
				break;

			case AFNUM_INET6:
				ptvcursor_add(cursor, hf_pgm_poll_path6, 16, ENC_NA);
				break;

			default:
				expert_add_info(pinfo, ti, &ei_address_format_invalid);
				break;
			}

			ptvcursor_add(cursor, hf_pgm_poll_backoff_ivl, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_rand_str, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_poll_matching_bmask, 4, ENC_BIG_ENDIAN);
			break;
		case PGM_POLR_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_polr);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_polr_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_polr_round, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_polr_res, 2, ENC_BIG_ENDIAN);
			break;
		case PGM_ACK_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_ack);
			ptvcursor_set_tree(cursor, type_tree);

			ptvcursor_add(cursor, hf_pgm_ack_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_ack_bitmap, 4, ENC_BIG_ENDIAN);
			break;
		}

		if (pgmhdr_opts & PGM_OPT)
			dissect_pgmopts(cursor, pinfo, pktname);

		if (isdata)
			decode_pgm_ports(tvb, ptvcursor_current_offset(cursor), pinfo, tree, pgmhdr_sport, pgmhdr_dport);

		ptvcursor_free(cursor);
	}
}
Exemple #10
0
/* entry point */
static gboolean dissect_lanforge(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item *ti;
    proto_item *tmp;
    proto_tree *lanforge_tree;
    guint32 offset = 0;
    nstime_t tstamp;
    guint32 tss;
    guint32 tmpi;
    guint32 pld_len;

    /* check for min size */
    if(tvb_length(tvb) < 28) {  /* Not a LANforge packet. */
        return FALSE;
    }

    /* check for magic number */
    if(tvb_memeql(tvb, 4, lanforge_magic, 4) == -1) { /* Not a LANforge packet. */
       return FALSE;
    }

    /* Make entries in Protocol column and Info column on summary display */

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

    if(check_col(pinfo->cinfo, COL_INFO)) {
        col_add_fstr(pinfo->cinfo, COL_INFO, "Seq: %u", tvb_get_ntohl(tvb, 16));
    }

    if(tree) {

        /* create display subtree for the protocol */

        ti = proto_tree_add_item(tree, proto_lanforge, tvb, 0, -1, FALSE);

        lanforge_tree = proto_item_add_subtree(ti, ett_lanforge);

        /* add items to the subtree */

        proto_tree_add_item(lanforge_tree, hf_lanforge_crc, tvb, offset, 4, FALSE);
        offset+=4;

        proto_tree_add_item(lanforge_tree, hf_lanforge_magic, tvb, offset, 4, FALSE);
        offset+=4;

        proto_tree_add_item(lanforge_tree, hf_lanforge_src_session, tvb, offset, 2, FALSE);
        offset+=2;

        proto_tree_add_item(lanforge_tree, hf_lanforge_dst_session, tvb, offset, 2, FALSE);
        offset+=2;

        pld_len = tvb_get_ntohs(tvb, offset);
        tmp = proto_tree_add_item(lanforge_tree, hf_lanforge_pld_len_l, tvb, offset, 2, FALSE);
        PROTO_ITEM_SET_GENERATED(tmp);
        offset+=2;

        tmpi = tvb_get_guint8(tvb, offset);
        tmp = proto_tree_add_item(lanforge_tree, hf_lanforge_pld_len_h, tvb, offset, 1, FALSE);
        PROTO_ITEM_SET_GENERATED(tmp);
        offset+=1;
        pld_len |= (tmpi << 16);

        proto_tree_add_uint(lanforge_tree, hf_lanforge_pld_len, tvb, offset-3, 3, pld_len);

        proto_tree_add_item(lanforge_tree, hf_lanforge_pld_pattern, tvb, offset, 1, FALSE);
        offset+=1;

        proto_tree_add_item(lanforge_tree, hf_lanforge_seq, tvb, offset, 4, FALSE);
        offset+=4;

        tss = tvb_get_ntohl(tvb, offset);
        tstamp.secs = tss;
        tmp = proto_tree_add_item(lanforge_tree, hf_lanforge_tx_time_s, tvb, offset, 4, FALSE);
        PROTO_ITEM_SET_GENERATED(tmp);
        offset+=4;

        tss = tvb_get_ntohl(tvb, offset);
        tstamp.nsecs = tss;
        tmp = proto_tree_add_item(lanforge_tree, hf_lanforge_tx_time_ns, tvb, offset, 4, FALSE);
        PROTO_ITEM_SET_GENERATED(tmp);
        offset+=4;

        proto_tree_add_time(lanforge_tree, hf_lanforge_timestamp, tvb, offset - 8, 8, &tstamp);

#if 0
        if(tvb_reported_length_remaining(tvb, offset) > 0) /* random data */
            proto_tree_add_text(lanforge_tree, tvb, offset, -1, "Data (%u bytes)",
                                tvb_length_remaining(tvb, offset));
#else
        if(tvb_reported_length_remaining(tvb, offset) > 0) /* random data */
            call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo,
                lanforge_tree);
#endif
    }

    return TRUE;
}
/* Code to actually dissect the packets */
static void
dissect_tte_pcf(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    /* Set up structures needed to add the protocol subtree and manage it */
    proto_item *tte_pcf_root_item;
    proto_tree *tte_pcf_tree;

    /* variables used to store the fields displayed in the info_column */
    guint8 sync_priority = 0;
    guint8 sync_domain   = 0;

    /* Check that there's enough data */
    if (tvb_length(tvb) < TTE_PCF_LENGTH )
    {
        return;
    }

    /* get sync_priority and sync_domain */
    sync_priority = tvb_get_guint8(tvb, TTE_PCF_IC_LENGTH+TTE_PCF_MN_LENGTH+
        TTE_PCF_RES0_LENGTH);
    sync_domain = tvb_get_guint8(tvb, TTE_PCF_IC_LENGTH+TTE_PCF_MN_LENGTH+
        TTE_PCF_RES0_LENGTH+TTE_PCF_SP_LENGTH);

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

    col_add_fstr(pinfo->cinfo, COL_INFO,
            "Sync Domain: 0x%02X  Sync Priority: 0x%02X",
            sync_domain, sync_priority);

    if (tree) {

        /* create display subtree for the protocol */
        tte_pcf_root_item = proto_tree_add_item(tree, proto_tte_pcf, tvb, 0,
            TTE_PCF_LENGTH, ENC_NA);

        tte_pcf_tree = proto_item_add_subtree(tte_pcf_root_item, ett_tte_pcf);

        proto_tree_add_item(tte_pcf_tree,
            hf_tte_pcf_ic, tvb, 0, TTE_PCF_IC_LENGTH, ENC_BIG_ENDIAN);

        proto_tree_add_item(tte_pcf_tree,
            hf_tte_pcf_mn, tvb, TTE_PCF_IC_LENGTH, TTE_PCF_MN_LENGTH, ENC_BIG_ENDIAN);

     /* RESERVED FIELD --- will not be displayed */
     /* proto_tree_add_item(tte_pcf_tree,
            hf_tte_pcf_res0, tvb, TTE_PCF_IC_LENGTH+TTE_PCF_MN_LENGTH,
            TTE_PCF_RES0_LENGTH, ENC_BIG_ENDIAN); */

        proto_tree_add_item(tte_pcf_tree,
            hf_tte_pcf_sp, tvb, TTE_PCF_IC_LENGTH+TTE_PCF_MN_LENGTH+
            TTE_PCF_RES0_LENGTH, TTE_PCF_SP_LENGTH, ENC_BIG_ENDIAN);

        proto_tree_add_item(tte_pcf_tree,
            hf_tte_pcf_sd, tvb, TTE_PCF_IC_LENGTH+TTE_PCF_MN_LENGTH+
            TTE_PCF_RES0_LENGTH+TTE_PCF_SP_LENGTH, TTE_PCF_SD_LENGTH, ENC_BIG_ENDIAN);

        proto_tree_add_item(tte_pcf_tree,
            hf_tte_pcf_type, tvb, TTE_PCF_IC_LENGTH+TTE_PCF_MN_LENGTH+
            TTE_PCF_RES0_LENGTH+TTE_PCF_SP_LENGTH+TTE_PCF_SD_LENGTH,
            TTE_PCF_TYPE_LENGTH, ENC_BIG_ENDIAN);

     /* RESERVED FIELD --- will not be displayed */
     /* proto_tree_add_item(tte_pcf_tree,
            hf_tte_pcf_res1, tvb, TTE_PCF_IC_LENGTH+TTE_PCF_MN_LENGTH+
            TTE_PCF_RES0_LENGTH+TTE_PCF_SP_LENGTH+TTE_PCF_SD_LENGTH+
            TTE_PCF_TYPE_LENGTH, TTE_PCF_RES1_LENGTH, ENC_NA); */

        proto_tree_add_item(tte_pcf_tree,
            hf_tte_pcf_tc, tvb, TTE_PCF_IC_LENGTH+TTE_PCF_MN_LENGTH+
            TTE_PCF_RES0_LENGTH+TTE_PCF_SP_LENGTH+TTE_PCF_SD_LENGTH+
            TTE_PCF_TYPE_LENGTH+TTE_PCF_RES1_LENGTH, TTE_PCF_TC_LENGTH, ENC_BIG_ENDIAN);
    }

}
Exemple #12
0
static void dissect_icp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree *icp_tree , *payload_tree;
    proto_item *ti;
    guint8 opcode;
    guint16 message_length;
    guint32 request_number;
    guint32 options;
    guint32 option_data;

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

    opcode=tvb_get_guint8(tvb, 0);
    message_length=tvb_get_ntohs(tvb, 2);
    request_number=tvb_get_ntohl(tvb, 4);

    col_add_fstr(pinfo->cinfo,COL_INFO,"Opcode: %s (%u), Req Nr: %u",
                 val_to_str_const(opcode, opcode_vals, "Unknown"), opcode,
                 request_number);

    if (tree)
    {

        ti = proto_tree_add_item(tree,proto_icp, tvb, 0, message_length, ENC_NA);
        icp_tree = proto_item_add_subtree(ti, ett_icp);

        proto_tree_add_uint(icp_tree,hf_icp_opcode, tvb, 0, 1, opcode);

        proto_tree_add_item(icp_tree,hf_icp_version, tvb, 1, 1, ENC_BIG_ENDIAN);

        proto_tree_add_uint(icp_tree,hf_icp_length, tvb, 2, 2, message_length);

        proto_tree_add_uint(icp_tree,hf_icp_request_nr, tvb, 4, 4,
                            request_number);

        options=tvb_get_ntohl(tvb, 8);
        if ( (opcode == CODE_ICP_OP_QUERY) && ((options & 0x80000000 ) != 0) )
        {
            proto_tree_add_text(icp_tree, tvb,8,4,
                                "option: ICP_FLAG_HIT_OBJ");
        }
        if ( (opcode == CODE_ICP_OP_QUERY)&& ((options & 0x40000000 ) != 0) )
        {
            proto_tree_add_text(icp_tree, tvb,8,4,
                                "option:ICP_FLAG_SRC_RTT");
        }
        if ((opcode != CODE_ICP_OP_QUERY)&& ((options & 0x40000000 ) != 0))
        {
            option_data=tvb_get_ntohl(tvb, 12);
            proto_tree_add_text(icp_tree, tvb,8,8,
                                "option: ICP_FLAG_SCR_RTT RTT=%u",
                                option_data & 0x0000ffff);
        }

        proto_tree_add_text(icp_tree, tvb, 16, 4,
                            "Sender Host IP address %s",
                            tvb_ip_to_str(tvb, 16));

        payload_tree = proto_tree_add_subtree(icp_tree, tvb,
                                              20, message_length - 20,
                                              ett_icp_payload, NULL, "Payload");
        dissect_icp_payload(tvb, 20, payload_tree, opcode);
    }
}
static void
dissect_wlancap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree *wlan_tree = NULL;
    proto_item *ti;
    tvbuff_t *next_tvb;
    int offset;
    guint32 version;
    guint32 length;
    guint32 channel;
    guint32 datarate;
    guint32 ssi_type;
    guint32 antnoise;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "WLAN");
    col_clear(pinfo->cinfo, COL_INFO);
    offset = 0;

    version = tvb_get_ntohl(tvb, offset) - WLANCAP_MAGIC_COOKIE_BASE;

    length = tvb_get_ntohl(tvb, offset+4);

    col_add_fstr(pinfo->cinfo, COL_INFO, "AVS WLAN Capture v%x, Length %d",version, length);

    if (version > 2) {
      goto skip;
    }

    /* Dissect the AVS header */
    if (tree) {
      ti = proto_tree_add_item(tree, proto_wlancap, tvb, 0, length, ENC_NA);
      wlan_tree = proto_item_add_subtree(ti, ett_radio);
      proto_tree_add_item(wlan_tree, hf_wlan_magic, tvb, offset, 4, ENC_BIG_ENDIAN);
      proto_tree_add_item(wlan_tree, hf_wlan_version, tvb, offset, 4, ENC_BIG_ENDIAN);
    }
    offset+=4;
    if (tree)
      proto_tree_add_item(wlan_tree, hf_wlan_length, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset+=4;
    if (tree)
      proto_tree_add_item(wlan_tree, hf_mactime, tvb, offset, 8, ENC_BIG_ENDIAN);
    offset+=8;
    if (tree)
      proto_tree_add_item(wlan_tree, hf_hosttime, tvb, offset, 8, ENC_BIG_ENDIAN);
    offset+=8;
    if (tree)
      proto_tree_add_item(wlan_tree, hf_wlan_phytype, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset+=4;

    /* XXX cook channel (fh uses different numbers) */
    channel = tvb_get_ntohl(tvb, offset);
    if (channel < 256) {
      col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", channel);
      if (tree)
        proto_tree_add_uint(wlan_tree, hf_channel, tvb, offset, 4, channel);
    } else if (channel < 10000) {
      col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u MHz", channel);
      if (tree)
        proto_tree_add_uint_format(wlan_tree, hf_channel_frequency, tvb, offset,
                                   4, channel, "Frequency: %u MHz", channel);
    } else {
      col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u KHz", channel);
      if (tree)
        proto_tree_add_uint_format(wlan_tree, hf_channel_frequency, tvb, offset,
                                   4, channel, "Frequency: %u KHz", channel);
    }
    offset+=4;
    datarate = tvb_get_ntohl(tvb, offset);
    if (datarate < 100000) {
      /* In units of 100 Kb/s; convert to b/s */
      datarate *= 100000;
    }

    col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u",
                   datarate / 1000000,
                   ((datarate % 1000000) > 500000) ? 5 : 0);
    if (tree) {
      proto_tree_add_uint64_format(wlan_tree, hf_data_rate, tvb, offset, 4,
                                   datarate,
                                   "Data Rate: %u.%u Mb/s",
                                   datarate/1000000,
                                   ((datarate % 1000000) > 500000) ? 5 : 0);
    }
    offset+=4;
    if (tree)
      proto_tree_add_item(wlan_tree, hf_wlan_antenna, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset+=4;
    if (tree)
      proto_tree_add_item(wlan_tree, hf_wlan_priority, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset+=4;
    ssi_type = tvb_get_ntohl(tvb, offset);
    if (tree)
      proto_tree_add_uint(wlan_tree, hf_wlan_ssi_type, tvb, offset, 4, ssi_type);
    offset+=4;
    switch (ssi_type) {

    case SSI_NONE:
    default:
      /* either there is no SSI information, or we don't know what type it is */
      break;

    case SSI_NORM_RSSI:
      /* Normalized RSSI */
      col_add_fstr(pinfo->cinfo, COL_RSSI, "%u (norm)", tvb_get_ntohl(tvb, offset));
      if (tree)
        proto_tree_add_item(wlan_tree, hf_normrssi_antsignal, tvb, offset, 4, ENC_BIG_ENDIAN);
      break;

    case SSI_DBM:
      /* dBm */
      col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", tvb_get_ntohl(tvb, offset));
      if (tree)
        proto_tree_add_item(wlan_tree, hf_dbm_antsignal, tvb, offset, 4, ENC_BIG_ENDIAN);
      break;

    case SSI_RAW_RSSI:
      /* Raw RSSI */
      col_add_fstr(pinfo->cinfo, COL_RSSI, "%u (raw)", tvb_get_ntohl(tvb, offset));
      if (tree)
        proto_tree_add_item(wlan_tree, hf_rawrssi_antsignal, tvb, offset, 4, ENC_BIG_ENDIAN);
      break;
    }
    offset+=4;
    antnoise = tvb_get_ntohl(tvb, offset);
    /* 0xffffffff means "hardware does not provide noise data" */
    if (antnoise != 0xffffffff) {
      switch (ssi_type) {

      case SSI_NONE:
      default:
        /* either there is no SSI information, or we don't know what type it is */
        break;

      case SSI_NORM_RSSI:
        /* Normalized RSSI */
        if (tree)
          proto_tree_add_uint(wlan_tree, hf_normrssi_antnoise, tvb, offset, 4, antnoise);
        break;

      case SSI_DBM:
        /* dBm */
        if (tree)
          proto_tree_add_int(wlan_tree, hf_dbm_antnoise, tvb, offset, 4, antnoise);
        break;

      case SSI_RAW_RSSI:
        /* Raw RSSI */
        if (tree)
          proto_tree_add_uint(wlan_tree, hf_rawrssi_antnoise, tvb, offset, 4, antnoise);
        break;
      }
    }
    offset+=4;
    if (tree)
      proto_tree_add_item(wlan_tree, hf_wlan_preamble, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset+=4;
    if (tree)
      proto_tree_add_item(wlan_tree, hf_wlan_encoding, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset+=4;
    if (version > 1) {
      if (tree)
        proto_tree_add_item(wlan_tree, hf_wlan_sequence, tvb, offset, 4, ENC_BIG_ENDIAN);
      offset+=4;
      if (tree)
        proto_tree_add_item(wlan_tree, hf_wlan_drops, tvb, offset, 4, ENC_BIG_ENDIAN);
      offset+=4;
      if (tree)
        proto_tree_add_item(wlan_tree, hf_wlan_receiver_addr, tvb, offset, 6, ENC_NA);
      offset+=6;
      if (tree)
        proto_tree_add_item(wlan_tree, hf_wlan_padding, tvb, offset, 2, ENC_NA);
      offset+=2;
    }


 skip:
    offset = length;

    /* dissect the 802.11 header next */
    next_tvb = tvb_new_subset_remaining(tvb, offset);
    call_dissector(ieee80211_handle, next_tvb, pinfo, tree);
}
/*
 * Dissect 802.11 with a variable-length link-layer header and a pseudo-
 * header containing radio information.
 */
static int
dissect_wlan_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void *data)
{
  struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
  proto_item *ti = NULL;
  proto_tree *radio_tree = NULL;
  float data_rate = 0.0f;
  gboolean have_data_rate = FALSE;
  gboolean has_short_preamble = FALSE;
  gboolean short_preamble = 1;

  guint frame_length = tvb_reported_length(tvb); /* length of 802.11 frame data */

  /* durations in microseconds */
  guint preamble = 0; /* duration of plcp */
  guint duration = 0; /* duration of whole frame (plcp + mac data + any trailing parts) */

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

  /* Calculate the data rate, if we have the necessary data */
  if (phdr->has_data_rate) {
    data_rate = phdr->data_rate * 0.5f;
    have_data_rate = TRUE;
  }

  if (phdr->has_signal_dbm) {
    col_add_fstr(pinfo->cinfo, COL_RSSI, "%d dBm", phdr->signal_dbm);
  } else if (phdr->has_signal_percent) {
    col_add_fstr(pinfo->cinfo, COL_RSSI, "%u%%", phdr->signal_percent);
  }

  if (tree) {
    ti = proto_tree_add_item(tree, proto_wlan_radio, tvb, 0, 0, ENC_NA);
    radio_tree = proto_item_add_subtree (ti, ett_wlan_radio);

    if (phdr->phy != PHDR_802_11_PHY_UNKNOWN) {
      proto_tree_add_uint(radio_tree, hf_wlan_radio_phy, tvb, 0, 0,
               phdr->phy);

      switch (phdr->phy) {

      case PHDR_802_11_PHY_11_FHSS:
      {
        struct ieee_802_11_fhss *info_fhss = &phdr->phy_info.info_11_fhss;

        if (info_fhss->has_hop_set) {
          proto_tree_add_uint(radio_tree, hf_wlan_radio_11_fhss_hop_set, tvb, 0, 0,
                   info_fhss->hop_set);
        }
        if (info_fhss->has_hop_pattern) {
          proto_tree_add_uint(radio_tree, hf_wlan_radio_11_fhss_hop_pattern, tvb, 0, 0,
                   info_fhss->hop_pattern);
        }
        if (info_fhss->has_hop_index) {
          proto_tree_add_uint(radio_tree, hf_wlan_radio_11_fhss_hop_index, tvb, 0, 0,
                   info_fhss->hop_index);
        }
        break;
      }

      case PHDR_802_11_PHY_11B:
      {
        struct ieee_802_11b *info_b = &phdr->phy_info.info_11b;

        has_short_preamble = info_b->has_short_preamble;
        short_preamble = info_b->short_preamble;

        if (has_short_preamble) {
          proto_tree_add_boolean(radio_tree, hf_wlan_radio_short_preamble, tvb, 0, 0,
                   short_preamble);
        }
        break;
      }

      case PHDR_802_11_PHY_11A:
      {
        struct ieee_802_11a *info_a = &phdr->phy_info.info_11a;

        if (info_a->has_channel_type) {
          proto_tree_add_uint(radio_tree, hf_wlan_radio_11a_channel_type, tvb, 0, 0,
                   info_a->channel_type);
        }
        if (info_a->has_turbo_type) {
          proto_tree_add_uint(radio_tree, hf_wlan_radio_11a_turbo_type, tvb, 0, 0,
                   info_a->turbo_type);
        }
        break;
      }

      case PHDR_802_11_PHY_11G:
      {
        struct ieee_802_11g *info_g = &phdr->phy_info.info_11g;

        has_short_preamble = info_g->has_short_preamble;
        short_preamble = info_g->short_preamble;

        if (has_short_preamble) {
          proto_tree_add_boolean(radio_tree, hf_wlan_radio_short_preamble, tvb, 0, 0,
                   short_preamble);
        }
        if (info_g->has_mode) {
          proto_tree_add_uint(radio_tree, hf_wlan_radio_11g_mode, tvb, 0, 0,
                   info_g->mode);
        }
        break;
      }

      case PHDR_802_11_PHY_11N:
        {
          struct ieee_802_11n *info_n = &phdr->phy_info.info_11n;
          guint bandwidth_40;

          if (info_n->has_mcs_index) {
            proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_mcs_index, tvb, 0, 0,
                     info_n->mcs_index);
          }

          if (info_n->has_bandwidth) {
            proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_bandwidth, tvb, 0, 0,
                     info_n->bandwidth);
          }

          if (info_n->has_short_gi) {
            proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_short_gi, tvb, 0, 0,
                     info_n->short_gi);
          }

          if (info_n->has_greenfield) {
            proto_tree_add_boolean(radio_tree, hf_wlan_radio_11n_greenfield, tvb, 0, 0,
                     info_n->greenfield);
          }

          if (info_n->has_fec) {
            proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_fec, tvb, 0, 0,
                     info_n->fec);
          }

          if (info_n->has_stbc_streams) {
            proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_stbc_streams, tvb, 0, 0,
                     info_n->stbc_streams);
          }

          if (info_n->has_ness) {
            proto_tree_add_uint(radio_tree, hf_wlan_radio_11n_ness, tvb, 0, 0,
                     info_n->ness);
          }

          /*
           * If we have all the fields needed to look up the data rate,
           * do so.
           */
          if (info_n->has_mcs_index &&
              info_n->has_bandwidth &&
              info_n->has_short_gi) {
            bandwidth_40 =
              (info_n->bandwidth == PHDR_802_11_BANDWIDTH_40_MHZ) ?
               1 : 0;
            if (info_n->mcs_index <= MAX_MCS_INDEX) {
              data_rate = ieee80211_htrate(info_n->mcs_index, bandwidth_40, info_n->short_gi);
              have_data_rate = TRUE;
            }
          }
        }
        break;

      case PHDR_802_11_PHY_11AC:
        {
          struct ieee_802_11ac *info_ac = &phdr->phy_info.info_11ac;
          gboolean can_calculate_rate;
          guint bandwidth = 0;
          guint i;

          if (info_ac->has_stbc) {
            proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_stbc, tvb, 0, 0,
                     info_ac->stbc);
          }

          if (info_ac->has_txop_ps_not_allowed) {
            proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_txop_ps_not_allowed, tvb, 0, 0,
                     info_ac->txop_ps_not_allowed);
          }

          if (info_ac->has_short_gi) {
            can_calculate_rate = TRUE;  /* well, if we also have the bandwidth */
            proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_short_gi, tvb, 0, 0,
                     info_ac->short_gi);
          } else {
            can_calculate_rate = FALSE; /* unknown GI length */
          }

          if (info_ac->has_short_gi_nsym_disambig) {
            proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_short_gi_nsym_disambig, tvb, 0, 0,
                     info_ac->short_gi_nsym_disambig);
          }

          if (info_ac->has_ldpc_extra_ofdm_symbol) {
            proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_ldpc_extra_ofdm_symbol, tvb, 0, 0,
                     info_ac->ldpc_extra_ofdm_symbol);
          }

          if (info_ac->has_beamformed) {
            proto_tree_add_boolean(radio_tree, hf_wlan_radio_11ac_beamformed, tvb, 0, 0,
                     info_ac->beamformed);
          }

          if (info_ac->has_bandwidth) {
            if (info_ac->bandwidth < G_N_ELEMENTS(ieee80211_vht_bw2rate_index))
              bandwidth = ieee80211_vht_bw2rate_index[info_ac->bandwidth];
            else
              can_calculate_rate = FALSE; /* unknown bandwidth */
            proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_bandwidth, tvb, 0, 0,
                     info_ac->bandwidth);
          } else {
            can_calculate_rate = FALSE;   /* no bandwidth */
          }

          for (i = 0; i < 4; i++) {

            if (info_ac->nss[i] != 0) {
              proto_item *it;
              proto_tree *user_tree;

              it = proto_tree_add_item(radio_tree, hf_wlan_radio_11ac_user, tvb, 0, 0, ENC_NA);
              proto_item_append_text(it, " %d: MCS %u", i, info_ac->mcs[i]);
              user_tree = proto_item_add_subtree(it, ett_wlan_radio_11ac_user);

              it = proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_mcs, tvb, 0, 0,
                      info_ac->mcs[i]);
              if (info_ac->mcs[i] > MAX_MCS_VHT_INDEX) {
                proto_item_append_text(it, " (invalid)");
              } else {
                proto_item_append_text(it, " (%s %s)",
                  ieee80211_vhtinfo[info_ac->mcs[i]].modulation,
                  ieee80211_vhtinfo[info_ac->mcs[i]].coding_rate);
              }

              proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_nss, tvb, 0, 0,
                       info_ac->nss[i]);
              /*
               * If we don't know whether space-time block coding is being
               * used, we don't know the number of space-time streams.
               */
              if (info_ac->has_stbc) {
                guint nsts;

                if (info_ac->stbc)
                  nsts = 2 * info_ac->nss[i];
                else
                  nsts = info_ac->nss[i];
                proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_nsts, tvb, 0, 0,
                       nsts);
              }
              if (info_ac->has_fec) {
                  proto_tree_add_uint(user_tree, hf_wlan_radio_11ac_fec, tvb, 0, 0,
                           (info_ac->fec >> i) & 0x01);
              }

              /*
               * If we can calculate the data rate for this user, do so.
               */
              if (can_calculate_rate && info_ac->mcs[i] <= MAX_MCS_VHT_INDEX) {
                data_rate = ieee80211_vhtrate(info_ac->mcs[i], bandwidth, info_ac->short_gi) * info_ac->nss[i];
                if (data_rate != 0.0f) {
                  proto_tree_add_float_format_value(user_tree, hf_wlan_radio_data_rate, tvb, 0, 0,
                        data_rate,
                        "%.1f Mb/s",
                       data_rate);
                }
              }
            }
          }

          if (info_ac->has_group_id) {
            proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_gid, tvb, 0, 0,
                     info_ac->group_id);
          }

          if (info_ac->has_partial_aid) {
            proto_tree_add_uint(radio_tree, hf_wlan_radio_11ac_p_aid, tvb, 0, 0,
                     info_ac->partial_aid);
          }
        }
        break;
      }
Exemple #15
0
static void
dissect_spx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*spx_tree = NULL;
	proto_item	*ti;
	tvbuff_t	*next_tvb;
	guint8		conn_ctrl;
	proto_tree	*cc_tree;
	guint8		datastream_type;
	const char	*datastream_type_string;
	guint16         spx_seq;
	const char	*spx_msg_string;
	guint16		low_socket, high_socket;
	guint32		src;
	conversation_t	*conversation;
	spx_hash_value	*pkt_value;
	spx_rexmit_info	*spx_rexmit_info_p;
	spx_info	spx_infox;

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

	if (tree) {
		ti = proto_tree_add_item(tree, proto_spx, tvb, 0, SPX_HEADER_LEN, ENC_NA);
		spx_tree = proto_item_add_subtree(ti, ett_spx);
	}

	conn_ctrl = tvb_get_guint8(tvb, 0);
	spx_msg_string = spx_conn_ctrl(conn_ctrl);
	if (check_col(pinfo->cinfo, COL_INFO))
		col_append_fstr(pinfo->cinfo, COL_INFO, " %s", spx_msg_string);
	if (tree) {
		ti = proto_tree_add_uint_format(spx_tree, hf_spx_connection_control, tvb,
						0, 1, conn_ctrl,
						"Connection Control: %s (0x%02X)",
						spx_msg_string, conn_ctrl);
		cc_tree = proto_item_add_subtree(ti, ett_spx_connctrl);
		proto_tree_add_boolean(cc_tree, hf_spx_connection_control_sys, tvb,
				       0, 1, conn_ctrl);
		proto_tree_add_boolean(cc_tree, hf_spx_connection_control_send_ack, tvb,
				       0, 1, conn_ctrl);
		proto_tree_add_boolean(cc_tree, hf_spx_connection_control_attn, tvb,
				       0, 1, conn_ctrl);
		proto_tree_add_boolean(cc_tree, hf_spx_connection_control_eom, tvb,
				       0, 1, conn_ctrl);
	}

	datastream_type = tvb_get_guint8(tvb, 1);
	datastream_type_string = spx_datastream(datastream_type);
	if (datastream_type_string != NULL) {
		if (check_col(pinfo->cinfo, COL_INFO))
			col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
			    datastream_type_string);
	}
	if (tree) {
		if (datastream_type_string != NULL) {
			proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
						   1, 1, datastream_type,
						   "Datastream Type: %s (0x%02X)",
						   datastream_type_string,
						   datastream_type);
		} else {
			proto_tree_add_uint_format(spx_tree, hf_spx_datastream_type, tvb,
						   1, 1, datastream_type,
						   "Datastream Type: 0x%02X",
						   datastream_type);
		}
		proto_tree_add_item(spx_tree, hf_spx_src_id, tvb,  2, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(spx_tree, hf_spx_dst_id, tvb,  4, 2, ENC_BIG_ENDIAN);
	}
	spx_seq = tvb_get_ntohs(tvb, 6);
	if (tree) {
		proto_tree_add_uint(spx_tree, hf_spx_seq_nr, tvb,  6, 2, spx_seq);
		proto_tree_add_item(spx_tree, hf_spx_ack_nr, tvb,  8, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(spx_tree, hf_spx_all_nr, tvb, 10, 2, ENC_BIG_ENDIAN);
	}

	/*
	 * SPX is Connection Oriented and Delivery Guaranteed.
	 * On the first pass, we need to flag retransmissions by the SPX
	 * protocol, so that subdissectors know whether a packet was
	 * retransmitted.
	 *
	 * We start out by creating a conversation for this direction of the
	 * IPX session; we use "pinfo->srcport" twice, so that we have
	 * separate conversations for the two directions.
	 *
	 * XXX - that might not work correctly if there's more than one
	 * SPX session using that source port; can that happen?  If so,
	 * we should probably use the direction, as well as the conversation,
	 * as part of the hash key; if we do that, we can probably just
	 * use PT_IPX as the port type, and possibly get rid of PT_NCP.
	 *
	 * According to
	 *
	 *	http://developer.novell.com/research/appnotes/1995/december/03/apv.htm
	 *
	 * the sequence number is not incremented for system packets, so
	 * presumably that means there is no notion of a system packet
	 * being retransmitted; that document also says that system
	 * packets are used as "I'm still here" keepalives and as
	 * acknowledgements (presumably meaning ACK-only packets), which
	 * suggests that they might not be ACKed and thus might not
	 * be retransmitted.
	 */
	if (conn_ctrl & SPX_SYS_PACKET) {
		/*
		 * It's a system packet, so it isn't a retransmission.
		 */
		spx_rexmit_info_p = NULL;
	} else {
		/*
		 * Not a system packet - check for retransmissions.
		 */
		if (!pinfo->fd->flags.visited) {
			conversation = find_conversation(pinfo->fd->num, &pinfo->src,
			    &pinfo->dst, PT_NCP, pinfo->srcport,
			    pinfo->srcport, 0);
			if (conversation == NULL) {
				/*
				 * It's not part of any conversation - create
				 * a new one.
				 */
				conversation = conversation_new(pinfo->fd->num, &pinfo->src,
				    &pinfo->dst, PT_NCP, pinfo->srcport,
				    pinfo->srcport, 0);
			}

			/*
			 * Now we'll hash the SPX header and use the result
			 * of that, plus the conversation, as a hash key to
			 * identify this packet.
			 *
			 * If we don't find it in the hash table, it's not a
			 * retransmission, otherwise it is.  If we don't find
			 * it, we enter it into the hash table, with the
			 * frame number.
			 * If we do, we attach to this frame a structure giving
			 * the frame number of the original transmission, so
			 * that we, and subdissectors, know it's a
			 * retransmission.
			 */
			src = tvb_get_ntohs(tvb, 0)+tvb_get_ntohs(tvb, 2)+tvb_get_ntohs(tvb, 4)+tvb_get_ntohs(tvb, 6)+tvb_get_ntohs(tvb, 8);
			pkt_value = spx_hash_lookup(conversation, src, spx_seq);
			if (pkt_value == NULL) {
				/*
				 * Not found in the hash table.
				 * Enter it into the hash table.
				 */
				pkt_value = spx_hash_insert(conversation, src,
				    spx_seq);
				pkt_value->spx_ack = tvb_get_ntohs(tvb, 8);
				pkt_value->spx_all = tvb_get_ntohs(tvb, 10);
				pkt_value->num = pinfo->fd->num;

				/*
				 * This is not a retransmission, so we shouldn't
				 * have any retransmission indicator.
				 */
				spx_rexmit_info_p = NULL;
			} else {
				/*
				 * Found in the hash table.  Mark this frame as
				 * a retransmission.
				 */
				spx_rexmit_info_p = se_new(spx_rexmit_info);
				spx_rexmit_info_p->num = pkt_value->num;
				p_add_proto_data(pinfo->fd, proto_spx,
				    spx_rexmit_info_p);
			}
		} else {
			/*
			 * Do we have per-packet SPX data for this frame?
			 * If so, it's a retransmission, and the per-packet
			 * data indicates which frame had the original
			 * transmission.
			 */
			spx_rexmit_info_p = (spx_rexmit_info *)p_get_proto_data(pinfo->fd,
			    proto_spx);
		}
	}

	/*
	 * It's a retransmission if we have a retransmission indicator.
	 * Flag this as a retransmission, but don't pass it to the
	 * subdissector.
	 */
	if (spx_rexmit_info_p != NULL) {
		if (check_col(pinfo->cinfo, COL_INFO)) {
			col_add_fstr(pinfo->cinfo, COL_INFO,
			    "[Retransmission] Original Packet %u",
			    spx_rexmit_info_p->num);
		}
		if (tree) {
			proto_tree_add_uint_format(spx_tree, hf_spx_rexmt_frame,
			    tvb, 0, 0, spx_rexmit_info_p->num,
			    "This is a retransmission of frame %u",
			    spx_rexmit_info_p->num);
			if (tvb_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
				proto_tree_add_text(spx_tree, tvb,
				    SPX_HEADER_LEN, -1,
				    "Retransmitted data");
			}
		}
		return;
	}

	if (tvb_reported_length_remaining(tvb, SPX_HEADER_LEN) > 0) {
		void* pd_save;
		/*
		 * Call subdissectors based on the IPX socket numbers; a
		 * subdissector might have registered with our IPX socket
		 * dissector table rather than the IPX dissector's socket
		 * dissector table.
		 *
		 * Assume the lower-numbered socket number is more likely
		 * to be the right one, along the lines of what we do for
		 * TCP and UDP.  We've seen NCP packets with a type of NCP,
		 * a source socket of IPX_SOCKET_NCP, and a destination
		 * socket of IPX_SOCKET_IPX_MESSAGE, and we've seen NCP
		 * packets with a type of NCP, a source socket of
		 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
		 * IPX_SOCKET_NCP.
		 */
		if (pinfo->srcport > pinfo->destport) {
			low_socket = pinfo->destport;
			high_socket = pinfo->srcport;
		} else {
			low_socket = pinfo->srcport;
			high_socket = pinfo->destport;
		}

		/*
		 * Pass information to subdissectors.
		 */
		spx_infox.eom = conn_ctrl & SPX_EOM;
		spx_infox.datastream_type = datastream_type;
		pd_save = pinfo->private_data;
		pinfo->private_data = &spx_infox;

		next_tvb = tvb_new_subset_remaining(tvb, SPX_HEADER_LEN);
		if (dissector_try_uint(spx_socket_dissector_table, low_socket,
		    next_tvb, pinfo, tree))
		{
			pinfo->private_data = pd_save;
			return;
		}
		if (dissector_try_uint(spx_socket_dissector_table, high_socket,
		    next_tvb, pinfo, tree))
		{
			pinfo->private_data = pd_save;
			return;
		}
		call_dissector(data_handle, next_tvb, pinfo, tree);
		pinfo->private_data = pd_save;
	}
}
static void
dissect_nettl(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
      proto_tree *nettl_tree;
      proto_item *nettl_item;

      pinfo->current_proto = "nettl";

      if (tree) {
	    nettl_item = proto_tree_add_protocol_format(tree, proto_nettl, tvb,
		0, -1, "HP-UX Network Tracing and Logging (nettl) header");
	    nettl_tree = proto_item_add_subtree(nettl_item, ett_nettl);
            proto_tree_add_uint_format(nettl_tree, hf_nettl_subsys, tvb,
		0, 0, pinfo->pseudo_header->nettl.subsys,
		"Subsystem: %d (%s)", pinfo->pseudo_header->nettl.subsys,
		val_to_str(pinfo->pseudo_header->nettl.subsys, subsystem, "Unknown"));
            proto_tree_add_int(nettl_tree, hf_nettl_devid, tvb,
		0, 0, pinfo->pseudo_header->nettl.devid);
            proto_tree_add_uint_format(nettl_tree, hf_nettl_kind, tvb,
		0, 0, pinfo->pseudo_header->nettl.kind,
		"Trace Kind: 0x%08x (%s)", pinfo->pseudo_header->nettl.kind,
		val_to_str(pinfo->pseudo_header->nettl.kind & ~NETTL_HDR_SUBSYSTEM_BITS_MASK, trace_kind, "Unknown"));
            proto_tree_add_int(nettl_tree, hf_nettl_pid, tvb,
		0, 0, pinfo->pseudo_header->nettl.pid);
            proto_tree_add_uint(nettl_tree, hf_nettl_uid, tvb,
		0, 0, pinfo->pseudo_header->nettl.uid);

      }

      switch (pinfo->fd->lnk_t) {
         case WTAP_ENCAP_NETTL_ETHERNET:
            call_dissector(eth_withoutfcs_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_TOKEN_RING:
            call_dissector(tr_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_FDDI:
            if (!dissector_try_port(wtap_dissector_table,
			WTAP_ENCAP_FDDI_BITSWAPPED, tvb, pinfo, tree))
	            call_dissector(data_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_RAW_IP:
            if ( (pinfo->pseudo_header->nettl.kind & NETTL_HDR_PDU_MASK) == 0 )
                    /* not actually a data packet (PDU) trace record */
	            call_dissector(data_handle, tvb, pinfo, tree);
            else if (pinfo->pseudo_header->nettl.subsys == NETTL_SUBSYS_NS_LS_SCTP )
                    call_dissector(sctp_handle, tvb, pinfo, tree);
            else if (!dissector_try_port(wtap_dissector_table,
			WTAP_ENCAP_RAW_IP, tvb, pinfo, tree))
	            call_dissector(data_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_RAW_ICMP:
            if (!dissector_try_port(ip_proto_dissector_table,
			IP_PROTO_ICMP, tvb, pinfo, tree))
	            call_dissector(data_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_RAW_ICMPV6:
            if (!dissector_try_port(ip_proto_dissector_table,
	                IP_PROTO_ICMPV6, tvb, pinfo, tree))
	            call_dissector(data_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_X25:
	    if (pinfo->pseudo_header->nettl.kind == NETTL_HDR_PDUIN)
            	pinfo->p2p_dir = P2P_DIR_RECV;
	    else if (pinfo->pseudo_header->nettl.kind == NETTL_HDR_PDUOUT)
            	pinfo->p2p_dir = P2P_DIR_SENT;
	    if (pinfo->pseudo_header->nettl.subsys == NETTL_SUBSYS_SX25L2)
            	call_dissector(lapb_handle, tvb, pinfo, tree);
	    else
            	call_dissector(x25_handle, tvb, pinfo, tree);
            break;
         case WTAP_ENCAP_NETTL_RAW_TELNET:
            if (!dissector_try_port(tcp_subdissector_table,
	                TCP_PORT_TELNET, tvb, pinfo, tree))
	            call_dissector(data_handle, tvb, pinfo, tree);
            break;
         default:
            col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
            if (check_col(pinfo->cinfo, COL_INFO))
                col_add_fstr(pinfo->cinfo, COL_INFO,
		"Unsupported nettl subsytem: %d (%s)",
                pinfo->pseudo_header->nettl.subsys,
		val_to_str(pinfo->pseudo_header->nettl.subsys, subsystem, "Unknown"));
            call_dissector(data_handle, tvb, pinfo, tree);
      }
}
Exemple #17
0
/* UA/UDP DISSECTOR */
static void _dissect_uaudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                           e_ua_direction direction)
{
    gint        offset = 0;
    guint32     type, length;
    guint8      opcode;
    proto_item *uaudp_item, *tlv_item, *tlv_len_item;
    proto_tree *uaudp_tree, *connect_tree;

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

    /* get the identifier; it means operation code */
    opcode = tvb_get_guint8(tvb, offset);
    offset += 1;

    ua_tap_info.opcode = opcode;
    ua_tap_info.expseq = 0;
    ua_tap_info.sntseq = 0;

    /* print in "INFO" column the type of UAUDP message */
    col_add_fstr(pinfo->cinfo,
                COL_INFO,
                "%s",
                val_to_str_ext(opcode, &uaudp_opcode_str_ext, "unknown (0x%02x)"));

    uaudp_item = proto_tree_add_protocol_format(tree, proto_uaudp, tvb, 0, tvb_reported_length(tvb),
                            "Universal Alcatel/UDP Encapsulation Protocol, %s",
                            val_to_str_ext(opcode, &uaudp_opcode_str_ext, "unknown (0x%02x)"));

    uaudp_tree = proto_item_add_subtree(uaudp_item, ett_uaudp);

    /* print the identifier */
    proto_tree_add_uint(uaudp_tree, hf_uaudp_opcode, tvb, 0, 1, opcode);

    switch(opcode)
    {
    case UAUDP_CONNECT:
    {
        while(tvb_reported_length_remaining(tvb, offset) > 0)
        {
            type = tvb_get_guint8(tvb, offset+0);
            connect_tree = proto_tree_add_subtree(uaudp_tree, tvb, offset, 0, ett_uaudp_tlv, &tlv_item,
                                                    val_to_str_ext(type, &uaudp_connect_vals_ext, "Unknown %d"));
            proto_tree_add_uint(connect_tree, hf_uaudp_type, tvb, offset, 1, type);
            offset++;
            tlv_len_item = proto_tree_add_item_ret_uint(connect_tree, hf_uaudp_length, tvb, offset, 1, ENC_NA, &length);
            proto_item_set_len(tlv_item, length+2);
            offset++;

            switch(type)
            {
            case UAUDP_CONNECT_VERSION:
                if ((length >= 1) && (length <= 4))
                {
                    proto_tree_add_item(connect_tree, hf_uaudp_version, tvb, offset, length, ENC_BIG_ENDIAN);
                }
                else
                {
                    expert_add_info_format(pinfo, tlv_len_item, &ei_uaudp_tlv_length, "Invalid length %d", length);
                }
                break;
            case UAUDP_CONNECT_WINDOW_SIZE:
                if ((length >= 1) && (length <= 4))
                {
                    proto_tree_add_item(connect_tree, hf_uaudp_window_size, tvb, offset, length, ENC_BIG_ENDIAN);
                }
                else
                {
                    expert_add_info_format(pinfo, tlv_len_item, &ei_uaudp_tlv_length, "Invalid length %d", length);
                }
                break;
            case UAUDP_CONNECT_MTU:
                if ((length >= 1) && (length <= 4))
                {
                    proto_tree_add_item(connect_tree, hf_uaudp_mtu, tvb, offset, length, ENC_BIG_ENDIAN);
                }
                else
                {
                    expert_add_info_format(pinfo, tlv_len_item, &ei_uaudp_tlv_length, "Invalid length %d", length);
                }
                break;
            case UAUDP_CONNECT_UDP_LOST:
                if ((length >= 1) && (length <= 4))
                {
                    proto_tree_add_item(connect_tree, hf_uaudp_udp_lost, tvb, offset, length, ENC_BIG_ENDIAN);
                }
                else
                {
                    expert_add_info_format(pinfo, tlv_len_item, &ei_uaudp_tlv_length, "Invalid length %d", length);
                }
                break;
            case UAUDP_CONNECT_UDP_LOST_REINIT:
                if ((length >= 1) && (length <= 4))
                {
                    proto_tree_add_item(connect_tree, hf_uaudp_udp_lost_reinit, tvb, offset, length, ENC_BIG_ENDIAN);
                }
                else
                {
                    expert_add_info_format(pinfo, tlv_len_item, &ei_uaudp_tlv_length, "Invalid length %d", length);
                }
                break;
            case UAUDP_CONNECT_KEEPALIVE:
                if ((length >= 1) && (length <= 4))
                {
                    proto_tree_add_item(connect_tree, hf_uaudp_keepalive, tvb, offset, length, ENC_BIG_ENDIAN);
                }
                else
                {
                    expert_add_info_format(pinfo, tlv_len_item, &ei_uaudp_tlv_length, "Invalid length %d", length);
                }
                break;
            case UAUDP_CONNECT_QOS_IP_TOS:
                if ((length >= 1) && (length <= 4))
                {
                    proto_tree_add_item(connect_tree, hf_uaudp_qos_ip_tos, tvb, offset, length, ENC_BIG_ENDIAN);
                }
                else
                {
                    expert_add_info_format(pinfo, tlv_len_item, &ei_uaudp_tlv_length, "Invalid length %d", length);
                }
                break;
            case UAUDP_CONNECT_QOS_8021_VLID:
                if ((length >= 1) && (length <= 4))
                {
                    proto_tree_add_item(connect_tree, hf_uaudp_qos_8021_vlid, tvb, offset, length, ENC_BIG_ENDIAN);
                }
                else
                {
                    expert_add_info_format(pinfo, tlv_len_item, &ei_uaudp_tlv_length, "Invalid length %d", length);
                }
                break;
            case UAUDP_CONNECT_QOS_8021_PRI:
                if ((length >= 1) && (length <= 4))
                {
                    proto_tree_add_item(connect_tree, hf_uaudp_qos_8021_pri, tvb, offset, length, ENC_BIG_ENDIAN);
                }
                else
                {
                    expert_add_info_format(pinfo, tlv_len_item, &ei_uaudp_tlv_length, "Invalid length %d", length);
                }
                break;
            case UAUDP_CONNECT_SUPERFAST_CONNECT:
                if ((length >= 1) && (length <= 4))
                {
                    proto_tree_add_item(connect_tree, hf_uaudp_superfast_connect, tvb, offset, length, ENC_BIG_ENDIAN);
                }
                else
                {
                    expert_add_info_format(pinfo, tlv_len_item, &ei_uaudp_tlv_length, "Invalid length %d", length);
                }
                break;
            }
            offset += length;
        }
        break;
    }

    case UAUDP_NACK:
    {
        proto_tree_add_item(uaudp_tree,
                    hf_uaudp_expseq,
                    tvb,
                    offset,
                    2,
                    ENC_BIG_ENDIAN);
        break;
    }

    case UAUDP_DATA:
    {
        int datalen;

        proto_tree_add_item_ret_uint(uaudp_tree,
                    hf_uaudp_expseq,
                    tvb,
                    offset+0,
                    2,
                    ENC_BIG_ENDIAN,
                    &ua_tap_info.expseq);

        proto_tree_add_item_ret_uint(uaudp_tree,
                    hf_uaudp_sntseq,
                    tvb,
                    offset+2,
                    2,
                    ENC_BIG_ENDIAN,
                    &ua_tap_info.sntseq);

        offset  += 4;
        datalen  = tvb_reported_length(tvb) - offset;

        /* if there is remaining data, call the UA dissector */
        if (datalen > 0)
        {
            if (direction == SYS_TO_TERM)
                call_dissector(ua_sys_to_term_handle,
                           tvb_new_subset_length(tvb, offset, datalen),
                           pinfo,
                           tree);
            else if (direction == TERM_TO_SYS)
                call_dissector(ua_term_to_sys_handle,
                           tvb_new_subset_length(tvb, offset, datalen),
                           pinfo,
                           tree);
            else {
                /* XXX: expert ?? */
                col_set_str(pinfo->cinfo,
                            COL_INFO,
                            "Data - Couldn't resolve direction. Check UAUDP Preferences.");
            }
            ua_tap_info.expseq = hf_uaudp_expseq;
        }
        else {
            /* print in "INFO" column */
            col_set_str(pinfo->cinfo,
                        COL_INFO,
                        "Data ACK");
        }
        break;
    }
    default:
        break;
    }
#if 0
    tap_queue_packet(uaudp_tap, pinfo, &ua_tap_info);
#endif
}
static void
dissect_socketcan(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree *can_tree;
	proto_item *ti;
	guint8      frame_type;
	gint        frame_len;
	struct can_identifier can_id;
	tvbuff_t*   next_tvb;

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

	frame_len  = tvb_get_guint8( tvb, CAN_LEN_OFFSET);
	can_id.id  = tvb_get_ntohl(tvb, 0);

	if (can_id.id & CAN_RTR_FLAG)
	{
		frame_type = LINUX_CAN_RTR;
	}
	else if (can_id.id & CAN_ERR_FLAG)
	{
		frame_type = LINUX_CAN_ERR;
	}
	else if (can_id.id & CAN_EFF_FLAG)
	{
		frame_type = LINUX_CAN_EXT;
	}
	else
	{
		frame_type = LINUX_CAN_STD;
	}

	can_id.id &= CAN_EFF_MASK;

	col_add_fstr(pinfo->cinfo, COL_INFO, "%s: 0x%08x",
		     val_to_str(frame_type, frame_type_vals, "Unknown (0x%02x)"), can_id.id);
	col_append_fstr(pinfo->cinfo, COL_INFO, "   %s",
			tvb_bytes_to_ep_str_punct(tvb, CAN_DATA_OFFSET, frame_len, ' '));

	ti       = proto_tree_add_item(tree, proto_can, tvb, 0, -1, ENC_NA);
	can_tree = proto_item_add_subtree(ti, ett_can);

	proto_tree_add_item(can_tree, hf_can_ident,   tvb, 0, 4, ENC_BIG_ENDIAN);
	proto_tree_add_item(can_tree, hf_can_extflag, tvb, 0, 4, ENC_BIG_ENDIAN);
	proto_tree_add_item(can_tree, hf_can_rtrflag, tvb, 0, 4, ENC_BIG_ENDIAN);
	proto_tree_add_item(can_tree, hf_can_errflag, tvb, 0, 4, ENC_BIG_ENDIAN);

	proto_tree_add_item(can_tree, hf_can_len,     tvb, CAN_LEN_OFFSET, 1, ENC_BIG_ENDIAN);

	next_tvb = tvb_new_subset_length(tvb, CAN_DATA_OFFSET, frame_len);

	switch (can_high_level_protocol_dissector)
	{
		case CAN_DATA_DISSECTOR:
			call_dissector(data_handle, next_tvb, pinfo, tree);
			break;
		case CAN_CANOPEN_DISSECTOR:
			call_dissector_with_data(canopen_handle, next_tvb, pinfo, tree, &can_id);
			break;
		case CAN_DEVICENET_DISSECTOR:
			/* XXX - Not sure this is correct.  But the capture provided in
             * bug 8564 provides CAN ID in little endian format, so this makes it work */
			can_id.id = GUINT32_SWAP_LE_BE(can_id.id);

			call_dissector_with_data(devicenet_handle, next_tvb, pinfo, tree, &can_id);
			break;
		case CAN_J1939_DISSECTOR:
			call_dissector_with_data(j1939_handle, next_tvb, pinfo, tree, &can_id);
			break;
	}
}
void
dissect_sss_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, guint8 subfunc, ncp_req_hash_value *request_value)
{
    guint32             foffset=0;
    guint32             subverb=0;
    guint32             msg_length=0;
    guint32             return_code=0;
    guint32             number_of_items=0;
    gint32              length_of_string=0;
    guint32             i = 0;
    const gchar		*str;

    proto_tree          *atree;
    proto_item          *aitem;
    proto_item          *expert_item;


    foffset = 8;
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "NSSS");
    if (tvb_length_remaining(tvb, foffset)<4) {
        return;
    }
    aitem = proto_tree_add_text(ncp_tree, tvb, foffset, -1, "Function: %s", val_to_str_const(subfunc, sss_func_enum, "Unknown"));
    atree = proto_item_add_subtree(aitem, ett_sss);
    switch (subfunc) {
    case 1:
        proto_tree_add_item(atree, hf_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        foffset += 4;
        proto_tree_add_item(atree, hf_sss_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        foffset += 4;
        break;
    case 2:
        if (request_value) {
            subverb = request_value->req_nds_flags;
            str = try_val_to_str(subverb, sss_verb_enum);
            if (str) {
                proto_tree_add_text(atree, tvb, foffset, tvb_length_remaining(tvb, foffset), "Verb: %s", str);
            }
        }
        proto_tree_add_item(atree, hf_length, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        msg_length = tvb_get_letohl(tvb, foffset);
        return_code = tvb_get_ntohl(tvb, foffset+msg_length);
        foffset += 4;
        proto_tree_add_item(atree, hf_frag_handle, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        foffset += 4;
        msg_length -= 4;
        if ((tvb_get_letohl(tvb, foffset-4)==0xffffffff) && (msg_length > 4))
        {
            foffset += 4;
            return_code = tvb_get_letohl(tvb, foffset);
            str = try_val_to_str(return_code, sss_errors_enum);
            if (str)
            {
                expert_item = proto_tree_add_item(atree, hf_return_code, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
                expert_add_info_format_text(pinfo, expert_item, &ei_return_code, "SSS Error: %s", str);
                col_add_fstr(pinfo->cinfo, COL_INFO, "R Error - %s", val_to_str(return_code, sss_errors_enum, "Unknown (%d)"));
                foffset+=4;
            }
            else
            {
                proto_tree_add_text(atree, tvb, foffset, 4, "Return Code: Success (0x00000000)");
                if (tvb_length_remaining(tvb, foffset) > 8) {
                    foffset += 4;
                    if (request_value && subverb == 6)
                    {
                        foffset += 4;
                        number_of_items = tvb_get_letohl(tvb, foffset);
                        foffset += 8;
                        for (i=0; i<number_of_items; i++)
                        {
                            length_of_string = find_delimiter(tvb, foffset);
                            if (length_of_string > tvb_length_remaining(tvb, foffset))
                            {
                                return;
                            }
                            foffset = sss_string(tvb, hf_secret, atree, foffset, TRUE, length_of_string);
                            if (tvb_length_remaining(tvb, foffset) < 8)
                            {
                                return;
                            }
                            foffset++;
                        }

                    }
                    else
                    {
                        proto_tree_add_item(atree, hf_enc_data, tvb, foffset, tvb_length_remaining(tvb, foffset), ENC_NA);
                    }
                }
            }
        }
        else
        {
            proto_tree_add_text(atree, tvb, foffset, 4, "Return Code: Success (0x00000000)");
            if (tvb_length_remaining(tvb, foffset) > 8) {
                foffset += 4;
                proto_tree_add_item(atree, hf_enc_data, tvb, foffset, tvb_length_remaining(tvb, foffset), ENC_NA);
            }
        }
        break;
    case 3:
        break;
    default:
        break;
    }
}
Exemple #20
0
/* UA/UDP DISSECTOR */
static void _dissect_uaudp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
                           e_ua_direction direction)
{
    gint        offset = 0;
    guint8      opcode;
    proto_item *uaudp_item;
    proto_tree *uaudp_tree;

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

    /* get the identifier; it means operation code */
    opcode = tvb_get_guint8(tvb, offset);
    offset += 1;

    ua_tap_info.opcode = opcode;
    ua_tap_info.expseq = 0;
    ua_tap_info.sntseq = 0;

    /* print in "INFO" column the type of UAUDP message */
    col_add_fstr(pinfo->cinfo,
                COL_INFO,
                "%s",
                val_to_str_ext(opcode, &uaudp_opcode_str_ext, "unknown (0x%02x)"));

    uaudp_item = proto_tree_add_protocol_format(tree, proto_uaudp, tvb, 0, 5,
                            "Universal Alcatel/UDP Encapsulation Protocol, %s",
                            val_to_str_ext(opcode, &uaudp_opcode_str_ext, "unknown (0x%02x)"));

    uaudp_tree = proto_item_add_subtree(uaudp_item, ett_uaudp);

    /* print the identifier */
    proto_tree_add_uint(uaudp_tree, hf_uaudp_opcode, tvb, 0, 1, opcode);

    switch(opcode)
    {
    case UAUDP_CONNECT:
    {
        if (!tree)
            break;
        while (tvb_offset_exists(tvb, offset))
        {
            guint8 T = tvb_get_guint8(tvb, offset+0);
            guint8 L = tvb_get_guint8(tvb, offset+1);

            switch(T)
            {
            case UAUDP_CONNECT_VERSION:
                rV(uaudp_tree, &hf_uaudp_version        , tvb, offset, L);
                break;
            case UAUDP_CONNECT_WINDOW_SIZE:
                rV(uaudp_tree, &hf_uaudp_window_size    , tvb, offset, L);
                break;
            case UAUDP_CONNECT_MTU:
                rV(uaudp_tree, &hf_uaudp_mtu            , tvb, offset, L);
                break;
            case UAUDP_CONNECT_UDP_LOST:
                rV(uaudp_tree, &hf_uaudp_udp_lost       , tvb, offset, L);
                break;
            case UAUDP_CONNECT_UDP_LOST_REINIT:
                rV(uaudp_tree, &hf_uaudp_udp_lost_reinit, tvb, offset, L);
                break;
            case UAUDP_CONNECT_KEEPALIVE:
                rV(uaudp_tree, &hf_uaudp_keepalive      , tvb, offset, L);
                break;
            case UAUDP_CONNECT_QOS_IP_TOS:
                rV(uaudp_tree, &hf_uaudp_qos_ip_tos     , tvb, offset, L);
                break;
            case UAUDP_CONNECT_QOS_8021_VLID:
                rV(uaudp_tree, &hf_uaudp_qos_8021_vlid  , tvb, offset, L);
                break;
            case UAUDP_CONNECT_QOS_8021_PRI:
                rV(uaudp_tree, &hf_uaudp_qos_8021_pri   , tvb, offset, L);
                break;
            }
            offset += (2 + L);
        }
        break;
    }

    case UAUDP_NACK:
    {
        proto_tree_add_uint(uaudp_tree,
                    hf_uaudp_expseq,
                    tvb,
                    offset,
                    2,
                    tvb_get_ntohs(tvb, offset));
        break;
    }

    case UAUDP_DATA:
    {
        int datalen;

        proto_tree_add_uint(uaudp_tree,
                    hf_uaudp_expseq,
                    tvb,
                    offset+0,
                    2,
                    tvb_get_ntohs(tvb, offset+0));

        proto_tree_add_uint(uaudp_tree,
                    hf_uaudp_sntseq,
                    tvb,
                    offset+2,
                    2,
                    tvb_get_ntohs(tvb, offset+2));

        ua_tap_info.expseq = hf_uaudp_expseq;
        ua_tap_info.sntseq = hf_uaudp_sntseq;

        offset  += 4;
        datalen  = tvb_reported_length(tvb) - offset;

        /* if there is remaining data, call the UA dissector */
        if (datalen > 0)
        {
            if (direction == SYS_TO_TERM)
                call_dissector(ua_sys_to_term_handle,
                           tvb_new_subset(tvb, offset, datalen, datalen),
                           pinfo,
                           tree);
            else if (direction == TERM_TO_SYS)
                call_dissector(ua_term_to_sys_handle,
                           tvb_new_subset(tvb, offset, datalen, datalen),
                           pinfo,
                           tree);
            else {
                /* XXX: expert ?? */
                col_add_str(pinfo->cinfo,
                            COL_INFO,
                            "Data - Couldn't resolve direction. Check UAUDP Preferences.");
            }
            ua_tap_info.expseq = hf_uaudp_expseq;
        }
        else {
            /* print in "INFO" column */
            col_add_str(pinfo->cinfo,
                        COL_INFO,
                        "Data ACK");
        }
        break;
    }
    default:
        break;
    }
#if 0
    tap_queue_packet(uaudp_tap, pinfo, &ua_tap_info);
#endif
}
static void
dissect_netrom_proto(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item   *ti;
	proto_tree   *netrom_tree;
	int           offset;
	const guint8 *src_addr;
	const guint8 *dst_addr;
	const guint8 *user_addr;
	const guint8 *node_addr;
#if 0
	guint8        src_ssid;
	guint8        dst_ssid;
#endif
	guint8        op_code;
	guint8        cct_index;
	guint8        cct_id;
	void         *saved_private_data;
	tvbuff_t     *next_tvb = NULL;

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

	offset = 0;

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

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

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

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

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

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

		ti = proto_tree_add_protocol_format( tree, proto_netrom, tvb, 0, NETROM_HEADER_SIZE,
			"NET/ROM, Src: %s (%s), Dst: %s (%s)",
			get_ax25_name( src_addr ),
			ax25_to_str( src_addr ),
			get_ax25_name( dst_addr ),
			ax25_to_str( dst_addr ) );

		netrom_tree = proto_item_add_subtree( ti, ett_netrom );

		offset = 0;

		/* source */
		proto_tree_add_ax25( netrom_tree, hf_netrom_src, tvb, offset, AX25_ADDR_LEN, src_addr );
		offset += AX25_ADDR_LEN;

		/* destination */
		proto_tree_add_ax25( netrom_tree, hf_netrom_dst, tvb, offset, AX25_ADDR_LEN, dst_addr );
		offset += AX25_ADDR_LEN;

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

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

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

						/* unused */
						offset += 1;

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

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

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;

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

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

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

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

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

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

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;

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

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

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;

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

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

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

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

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

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

						/* unused */
						offset += 1;

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

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

						break;
			}

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

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

						user_addr = tvb_get_ptr( tvb,  offset, AX25_ADDR_LEN );
						proto_tree_add_ax25( netrom_tree, hf_netrom_user, tvb, offset, AX25_ADDR_LEN, user_addr );
						offset += AX25_ADDR_LEN;

						node_addr = tvb_get_ptr( tvb,  offset, AX25_ADDR_LEN );
						proto_tree_add_ax25( netrom_tree, hf_netrom_node, tvb, offset, AX25_ADDR_LEN, node_addr );
						offset += AX25_ADDR_LEN;

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

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

	/* Call sub-dissectors here */

	saved_private_data = pinfo->private_data;
	next_tvb = tvb_new_subset_remaining(tvb, offset);

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

					break;
		case NETROM_INFO	:
		default			:
					call_dissector( default_handle , next_tvb, pinfo, tree );
					break;
		}

	pinfo->private_data = saved_private_data;
}
Exemple #22
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;
	const guchar	*line;
	gint		next_offset;
	int		linelen;
	int		tokenlen;
	const guchar	*next_token;

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


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

	if (check_col(pinfo->cinfo, COL_INFO)) {
		/*
		 * 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));
	}

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

		if (is_request) {
			hidden_item = proto_tree_add_boolean(imap_tree,
						      hf_imap_request, tvb, 0, 0, TRUE);
		} else {
			hidden_item = proto_tree_add_boolean(imap_tree,
						      hf_imap_response, tvb, 0, 0, TRUE);
		}
		PROTO_ITEM_SET_HIDDEN(hidden_item);

		while(tvb_length_remaining(tvb, offset) > 2) {

			/*
			 * 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_text(imap_tree, tvb, offset,
						 next_offset - offset, "%s",
						 tvb_format_text(tvb, offset, next_offset - offset));
			reqresp_tree = proto_item_add_subtree(ti, ett_imap_reqresp);

			/*
			 * 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) {
				if (is_request) {
					proto_tree_add_text(reqresp_tree, tvb, offset,
							    tokenlen, "Request Tag: %s",
							    format_text(line, tokenlen));
				} else {
					proto_tree_add_text(reqresp_tree, tvb, offset,
							    tokenlen, "Response Tag: %s",
							    format_text(line, tokenlen));
				}
				offset += (gint) (next_token - line);
				linelen -= (int) (next_token - line);
				line = next_token;
			}

			/*
			 * Add the rest of the line as request or reply data.
			 */
			if (linelen != 0) {
				if (is_request) {
					proto_tree_add_text(reqresp_tree, tvb, offset,
							    linelen, "Request: %s",
							    format_text(line, linelen));
				} else {
					proto_tree_add_text(reqresp_tree, tvb, offset,
							    linelen, "Response: %s",
							    format_text(line, linelen));
				}
			}

			offset += linelen+2; /* Skip over last line and \r\n at the end of it */

		}
	}
}
Exemple #23
0
/*
 * Dissect ASCII TPKT-encapsulated data in a TCP stream.
 */
void
dissect_asciitpkt(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
		  dissector_handle_t subdissector_handle)
{
    proto_item *ti = NULL;
    proto_tree *tpkt_tree = NULL;
    volatile int offset = 0;
    int length_remaining;
    int data_len;
    volatile int mgcp_packet_len = 0;
    int mgcp_version = 0;
    int mgcp_reserved = 0;
    volatile int length;
    tvbuff_t *volatile next_tvb;
    const char *saved_proto;
    guint8 string[4];
    void *pd_save;

    /*
     * If we're reassembling segmented TPKT PDUs, empty the COL_INFO
     * column, so subdissectors can append information
     * without having to worry about emptying the column.
     *
     * We use "col_add_str()" because the subdissector
     * might be appending information to the column, in
     * which case we'd have to zero the buffer out explicitly
     * anyway.
     */
    if (tpkt_desegment)
        col_set_str(pinfo->cinfo, COL_INFO, "");

    while (tvb_reported_length_remaining(tvb, offset) != 0) {
        /*
         * Is the first byte of this putative TPKT header
         * a valid TPKT version number, i.e. 3?
         */
        if (tvb_get_guint8(tvb, offset) != 48) {
            /*
             * No, so don't assume this is a TPKT header;
             * we might be in the middle of TPKT data,
             * so don't get the length and don't try to
             * do reassembly.
             */
            col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
            col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
            if (tree) {
                ti = proto_tree_add_item(tree, proto_tpkt, tvb,
                    offset, -1, ENC_NA);
                tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
                proto_item_set_text(ti, "TPKT");

                proto_tree_add_text(tpkt_tree, tvb, offset, -1,
                    "Continuation data");
            }
            return;
        }

        length_remaining = tvb_length_remaining(tvb, offset);

        /*
         * Get the length from the TPKT header.
         */

        tvb_memcpy(tvb, (guint8 *)string, offset, 2);
        mgcp_version = parseVersionText(string);
        tvb_memcpy(tvb, (guint8 *)string, offset +2, 2);
        mgcp_reserved = parseReservedText(string);
        tvb_memcpy(tvb, (guint8 *)string, offset + 4, 4);
        mgcp_packet_len = parseLengthText(string);
        data_len = mgcp_packet_len;

        /*
         * Dissect the TPKT header.
         * Save and restore "pinfo->current_proto".
         */
        saved_proto = pinfo->current_proto;
        pinfo->current_proto = "TPKT";

        col_set_str(pinfo->cinfo, COL_PROTOCOL, "TPKT");
        /*
         * Don't add the TPKT header information if we're
         * reassembling segmented TPKT PDUs or if this
         * PDU isn't reassembled.
         *
         * XXX - the first is so that subdissectors can append
         * information without getting TPKT stuff in the middle;
         * why the second?
         */
        if (!tpkt_desegment && !pinfo->fragmented) {
            col_add_fstr(pinfo->cinfo, COL_INFO,
                "TPKT Data length = %u", data_len);
        }

        if (tree) {
            ti = proto_tree_add_item(tree, proto_tpkt, tvb,
                offset, 8, ENC_NA);
            tpkt_tree = proto_item_add_subtree(ti, ett_tpkt);
            proto_item_set_text(ti, "TPKT");

            /* Version */
            proto_tree_add_uint(tpkt_tree, hf_tpkt_version, tvb,
                            offset, 2, mgcp_version);

            /* Reserved octet*/
            proto_tree_add_uint(tpkt_tree, hf_tpkt_reserved, tvb,
                            offset + 2, 2, mgcp_reserved);

            /* Length */
            proto_tree_add_uint(tpkt_tree, hf_tpkt_length, tvb,
                            offset + 4, 4, mgcp_packet_len);
        }
        pinfo->current_proto = saved_proto;

        /* Skip the TPKT header. */
        offset += TEXT_LAYER_LENGTH;
        length = length_remaining - TEXT_LAYER_LENGTH;
        if (length > data_len)
            length = data_len;

        next_tvb = tvb_new_subset(tvb, offset,length, data_len);

        /*
         * Call the subdissector.
         *
         * If it gets an error that means there's no point in
         * dissecting any more TPKT messages, rethrow the
         * exception in question.
         *
         * If it gets any other error, report it and continue, as that
         * means that TPKT message got an error, but that doesn't mean
         * we should stop dissecting TPKT messages within this frame
         * or chunk of reassembled data.
         */
	pd_save = pinfo->private_data;
        TRY {
            call_dissector(subdissector_handle, next_tvb, pinfo,
                tree);
        }
        CATCH_NONFATAL_ERRORS {
	    /*  Restore the private_data structure in case one of the
	     *  called dissectors modified it (and, due to the exception,
	     *  was unable to restore it).
	     */
	    pinfo->private_data = pd_save;

            show_exception(tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);
        }
        ENDTRY;

        /*
         * Skip the payload.
         */
        offset += data_len;
    }
}
Exemple #24
0
static void
dissect_stt_tree(tvbuff_t *tvb, packet_info *pinfo, proto_tree *stt_tree,
                 proto_item *stt_item)
{
    proto_tree *vlan_tree;
    proto_item *ver_item, *l4_offset_item, *vlan_item, *mss_item;
    guint8 flags;
    guint32 version, l4_offset, mss, attributes;
    guint64 context_id;
    int offset = STT_TCP_HDR_LEN;

    /*
        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |  Version      | Flags         |  L4 Offset    |  Reserved     |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |    Max. Segment Size          | PCP |V|     VLAN ID           |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |                                                               |
       +                     Context ID (64 bits)                      +
       |                                                               |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
       |     Padding                   |    Data                       |
       +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
       |                                                               |
    */

    /* Protocol version */
    ver_item = proto_tree_add_item_ret_uint(stt_tree, hf_stt_version, tvb,
                                            offset, 1, ENC_BIG_ENDIAN, &version);
    if (version != 0) {
        expert_add_info_format(pinfo, ver_item, &ei_stt_ver_unknown,
                               "Unknown version %u", version);
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown STT version %u", version);
    }
    offset++;

    /* Flags */
    flags = tvb_get_guint8(tvb, offset);
    offset = dissect_stt_flags(stt_tree, tvb, offset);

    /* Layer 4 offset */
    l4_offset_item = proto_tree_add_item_ret_uint(stt_tree, hf_stt_l4_offset,
                                                  tvb, offset, 1,
                                                  ENC_BIG_ENDIAN, &l4_offset);
    /* Display an error if offset is != 0 when offloading is not in use */
    if ( !(flags & FLAG_OFFLOAD_MASK) && (l4_offset != 0) ) {
        expert_add_info_format(pinfo, l4_offset_item, &ei_stt_l4_offset, "Incorrect offset, should be equal to zero");
    }
    /* Display an error if offset equals 0 when there is offloading */
    if ( (flags & FLAG_OFFLOAD_MASK) && (l4_offset == 0) ) {
        expert_add_info_format(pinfo, l4_offset_item, &ei_stt_l4_offset, "Incorrect offset, should be greater than zero");
    }
    offset ++;

    /* Reserved field (1 byte). MUST be 0 on transmission,
    ignored on receipt. */
    proto_tree_add_item(stt_tree, hf_stt_reserved_8, tvb, offset, 1,
                        ENC_BIG_ENDIAN);
    offset ++;

    /* Maximum Segment Size. MUST be 0 if segmentation offload
    is not in use. */
    mss_item = proto_tree_add_item_ret_uint(stt_tree, hf_stt_mss, tvb,
                                            offset, 2, ENC_BIG_ENDIAN, &mss);
    /* Display an error if MSS is != 0 when offloading is not in use */
    if ( !(flags & FLAG_OFFLOAD_MASK) && (mss != 0) ) {
        expert_add_info_format(pinfo, mss_item, &ei_stt_mss, "Incorrect max segment size, should be equal to zero");
    }
    offset += 2;

    /* Tag Control Information like header. If V flag is set, it
       indicates the presence of a valid VLAN ID in the following field
       and valid PCP in the preceding field. */
    vlan_item = proto_tree_add_item_ret_uint(stt_tree, hf_stt_vlan, tvb, offset,
                                             2, ENC_BIG_ENDIAN, &attributes);
    vlan_tree = proto_item_add_subtree(vlan_item, ett_stt_vlan);
    proto_item_set_text(vlan_item, "VLAN Priority %u, ID %u",
                        (attributes >> 13), (attributes & STT_VLANID_MASK));

    proto_tree_add_item(vlan_tree, hf_stt_pcp, tvb, offset, 2, ENC_BIG_ENDIAN);
    proto_tree_add_item(vlan_tree, hf_stt_v, tvb, offset, 2, ENC_BIG_ENDIAN);
    proto_tree_add_item(vlan_tree, hf_stt_vlan_id, tvb, offset, 2, ENC_BIG_ENDIAN);
    if (attributes & STT_V_MASK) {
        /* Display priority code point and VLAN ID when V flag is set */
        proto_item_append_text(stt_item, ", Priority: %u, VLAN ID: %u",
                               attributes >> 13,
                               attributes & STT_VLANID_MASK);
    }
/*FUNCTION:------------------------------------------------------
 *  NAME
 *      dissect_zep
 *  DESCRIPTION
 *      IEEE 802.15.4 packet dissection routine for Wireshark.
 *  PARAMETERS
 *      tvbuff_t *tvb       - pointer to buffer containing raw packet.
 *      packet_info *pinfo  - pointer to packet information fields
 *      proto_tree *tree    - pointer to data tree Wireshark uses to display packet.
 *  RETURNS
 *      void
 *---------------------------------------------------------------
 */
static void dissect_zep(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    tvbuff_t            *next_tvb;
    proto_item          *proto_root, *pi;
    proto_tree          *zep_tree;
    guint8              ieee_packet_len;
    guint8              zep_header_len;
    zep_info            zep_data;

    dissector_handle_t  next_dissector;

    /*  Determine whether this is a Q51/IEEE 802.15.4 sniffer packet or not */
    if(strcmp(tvb_get_ephemeral_string(tvb, 0, 2), ZEP_PREAMBLE)){
        /*  This is not a Q51/ZigBee sniffer packet */
        call_dissector(data_handle, tvb, pinfo, tree);
        return;
    }

    memset(&zep_data, 0, sizeof(zep_data)); /* Zero all zep_data fields. */

    /*  Extract the protocol version from the ZEP header. */
    zep_data.version = tvb_get_guint8(tvb, 2);
    if (zep_data.version == 1) {
        /* Type indicates a ZEP_v1 packet. */

        zep_header_len = ZEP_V1_HEADER_LEN;
        zep_data.type = 0;
        zep_data.channel_id = tvb_get_guint8(tvb, 3);
        zep_data.device_id = tvb_get_ntohs(tvb, 4);
        zep_data.lqi_mode = tvb_get_guint8(tvb, 6)?1:0;
        zep_data.lqi = tvb_get_guint8(tvb, 7);
        ieee_packet_len = (tvb_get_guint8(tvb, ZEP_V1_HEADER_LEN - 1) & ZEP_LENGTH_MASK);
    }
    else {
        /* At the time of writing, v2 is the latest version of ZEP, assuming
         * anything higher than v2 has identical format. */

        zep_data.type = tvb_get_guint8(tvb, 3);
        if (zep_data.type == ZEP_V2_TYPE_ACK) {
            /* ZEP Ack has only the seqno. */
            zep_header_len = ZEP_V2_ACK_LEN;
            zep_data.seqno = tvb_get_ntohl(tvb, 4);
            ieee_packet_len = 0;
        }
        else {
            /* Although, only type 1 corresponds to data, if another value is present, assume it is dissected the same. */
            zep_header_len = ZEP_V2_HEADER_LEN;
            zep_data.channel_id = tvb_get_guint8(tvb, 4);
            zep_data.device_id = tvb_get_ntohs(tvb, 5);
            zep_data.lqi_mode = tvb_get_guint8(tvb, 7)?1:0;
            zep_data.lqi = tvb_get_guint8(tvb, 8);
            ntp_to_nstime(tvb, 9, &(zep_data.ntp_time));
            zep_data.seqno = tvb_get_ntohl(tvb, 17);
            ieee_packet_len = (tvb_get_guint8(tvb, ZEP_V2_HEADER_LEN - 1) & ZEP_LENGTH_MASK);
        }
    }

#if 0
/*??dat*/
    if (zep_data.ntp_time.secs && zep_data.ntp_time.nsecs) {
        pinfo->fd->abs_ts = zep_data.ntp_time;
    }
#endif

    if(ieee_packet_len < tvb_length(tvb)-zep_header_len){
        /* Packet's length is mis-reported, abort dissection */
        call_dissector(data_handle, tvb, pinfo, tree);
        return;
    }

    /*  Enter name info protocol field */
    if(check_col(pinfo->cinfo, COL_PROTOCOL)){
        col_set_str(pinfo->cinfo, COL_PROTOCOL, (zep_data.version==2)?"ZEPv2":"ZEPv3");
    }

    /*  Enter name info protocol field */
    if(check_col(pinfo->cinfo, COL_INFO)){
        col_clear(pinfo->cinfo, COL_INFO);
        if (!((zep_data.version>=2) && (zep_data.type==ZEP_V2_TYPE_ACK))) col_add_fstr(pinfo->cinfo, COL_INFO, "Encapsulated ZigBee Packet [Channel]=%i [Length]=%i", zep_data.channel_id, ieee_packet_len);
        else col_add_fstr(pinfo->cinfo, COL_INFO, "Ack, Sequence Number: %i", zep_data.seqno);
    }

    if(tree){
        /*  Create subtree for the ZEP Header */
        if (!((zep_data.version>=2) && (zep_data.type==ZEP_V2_TYPE_ACK))) {
            proto_root = proto_tree_add_protocol_format(tree, proto_zep, tvb, 0, zep_header_len, "ZigBee Encapsulation Protocol, Channel: %i, Length: %i", zep_data.channel_id, ieee_packet_len);
        }
        else {
            proto_root = proto_tree_add_protocol_format(tree, proto_zep, tvb, 0, zep_header_len, "ZigBee Encapsulation Protocol, Ack");
        }
        zep_tree = proto_item_add_subtree(proto_root, ett_zep);

        /*  Display the information in the subtree */
        proto_tree_add_text(zep_tree, tvb, 0, 2, "Protocol ID String: EX ");
        if (zep_data.version==1) {
            proto_tree_add_uint(zep_tree, hf_zep_version, tvb, 2, 1, zep_data.version);
            proto_tree_add_uint(zep_tree, hf_zep_channel_id, tvb, 3, 1, zep_data.channel_id);
            proto_tree_add_uint(zep_tree, hf_zep_device_id, tvb, 4, 2, zep_data.device_id);
            proto_tree_add_boolean_format(zep_tree, hf_zep_lqi_mode, tvb, 6, 1, zep_data.lqi_mode, "LQI/CRC Mode: %s", zep_data.lqi_mode?"CRC":"LQI");
            if(!(zep_data.lqi_mode)){
                proto_tree_add_uint(zep_tree, hf_zep_lqi, tvb, 7, 1, zep_data.lqi);
            }
            proto_tree_add_text(zep_tree, tvb, 7+((zep_data.lqi_mode)?0:1), 7+((zep_data.lqi_mode)?1:0), "Reserved Fields");
        }
        else {
            proto_tree_add_uint(zep_tree, hf_zep_version, tvb, 2, 1, zep_data.version);
            if (zep_data.type == ZEP_V2_TYPE_ACK) {
                proto_tree_add_uint_format(zep_tree, hf_zep_version, tvb, 3, 1, zep_data.type, "Type: %i (Ack)", ZEP_V2_TYPE_ACK);
                proto_tree_add_uint(zep_tree, hf_zep_seqno, tvb, 4, 4, zep_data.seqno);
            }
            else {
                proto_tree_add_uint_format(zep_tree, hf_zep_version, tvb, 3, 1, zep_data.type, "Type: %i (%s)", zep_data.type, (zep_data.type==ZEP_V2_TYPE_DATA)?"Data":"Reserved");
                proto_tree_add_uint(zep_tree, hf_zep_channel_id, tvb, 4, 1, zep_data.channel_id);
                proto_tree_add_uint(zep_tree, hf_zep_device_id, tvb, 5, 2, zep_data.device_id);
                proto_tree_add_boolean_format(zep_tree, hf_zep_lqi_mode, tvb, 7, 1, zep_data.lqi_mode, "LQI/CRC Mode: %s", zep_data.lqi_mode?"CRC":"LQI");
                if(!(zep_data.lqi_mode)){
                    proto_tree_add_uint(zep_tree, hf_zep_lqi, tvb, 8, 1, zep_data.lqi);
                }
                pi = proto_tree_add_time(zep_tree, hf_zep_timestamp, tvb, 9, 8, &(zep_data.ntp_time));
                proto_item_append_text(pi, " (%ld.%09ds)", (long)zep_data.ntp_time.secs, zep_data.ntp_time.nsecs);
                proto_tree_add_uint(zep_tree, hf_zep_seqno, tvb, 17, 4, zep_data.seqno);
            }
        }
        if (!((zep_data.version==2) && (zep_data.type==ZEP_V2_TYPE_ACK))) proto_tree_add_uint_format(zep_tree, hf_zep_ieee_length, tvb, zep_header_len - 1, 1, ieee_packet_len, "Length: %i %s", ieee_packet_len, (ieee_packet_len==1)?"Byte":"Bytes");
    }

    /* Determine which dissector to call next. */
    if (zep_data.lqi_mode) {
        /* CRC present, use standard IEEE dissector. */
        next_dissector = ieee802154_ccfcs_handle; // testing, ignore liq_mode 0, was:ieee802154_handle;
    }
    else {
        /* ChipCon compliant FCS present. */
        next_dissector = ieee802154_ccfcs_handle;
//
    }
  
    if (zep_data.version>=3) {
	/* IEEE 802.15.4e dissector */	
	next_dissector = ieee802154e_handle;
    }
	
    if (!next_dissector) {
        /* IEEE 802.15.4 dissectors couldn't be found. */
        next_dissector = data_handle;
    }

    /*  Call the IEEE 802.15.4 dissector */
    if (!((zep_data.version>=2) && (zep_data.type==ZEP_V2_TYPE_ACK))) {
        next_tvb = tvb_new_subset(tvb, zep_header_len, ieee_packet_len, ieee_packet_len);
        call_dissector(next_dissector, next_tvb, pinfo, tree);
    }
} /* dissect_ieee802_15_4 */
/* Dissect a TS2 packet */
static void dissect_ts2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	ts2_conversation *conversation_data;
	guint16 type = tvb_get_letohs(tvb, 2);
	guint16 klass = tvb_get_letohs(tvb, 0);

	conversation_data = ts2_get_conversation(pinfo);

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

	if (check_col(pinfo->cinfo, COL_INFO)) {
		if(klass==TS2C_ACK)
			col_add_fstr(pinfo->cinfo, COL_INFO, "Class: %s", val_to_str(klass, classnames, "Unknown (0x%02x)"));
		else
			col_add_fstr(pinfo->cinfo, COL_INFO, "Type: %s, Class: %s", val_to_str(type, typenames, "Unknown (0x%02x)"), val_to_str(klass, classnames, "Unknown (0x%02x)"));
	}

	/* XXX: We need to do all the non GUI stuff whether or not if(tree) */
        /*      Do only once by checking visited ?                          */
        /*      ToDo: Rewrite ??                                            */
	if (!tree) {
		switch(klass) {
			case TS2C_CONNECTION:
				switch(type) {
					case TS2T_LOGINREQUEST:
						conversation_data->server_port=pinfo->destport;
						conversation_data->server_addr=pinfo->dst;
						break;
				}
				break;
			case TS2C_STANDARD:
				ts2_standard_dissect(tvb, pinfo, tree, conversation_data);
				break;
		}
	}

	if (tree) { /* we are being asked for details */
		proto_item *ti = NULL;
		proto_tree *ts2_tree = NULL;

		ti = proto_tree_add_item(tree, proto_ts2, tvb, 0, -1, TRUE);
		ts2_tree = proto_item_add_subtree(ti, ett_ts2);

		proto_tree_add_item(ts2_tree, hf_ts2_class, tvb, 0, 2, TRUE);
		if(klass==TS2C_ACK)
			proto_tree_add_item(ts2_tree, hf_ts2_resend_count, tvb, 2, 2, TRUE);
		else
			proto_tree_add_item(ts2_tree, hf_ts2_type, tvb, 2, 2, TRUE);

		proto_tree_add_item(ts2_tree, hf_ts2_sessionkey, tvb, 4, 4, TRUE);
		proto_tree_add_item(ts2_tree, hf_ts2_clientid, tvb, 8, 4, TRUE);
		switch(klass)
		{
			case TS2C_CONNECTION:
				proto_tree_add_item(ts2_tree, hf_ts2_seqnum, tvb, 12, 4, TRUE);
				ts2_add_checked_crc32(ts2_tree, hf_ts2_crc32, tvb, 16, tvb_get_letohl(tvb, 16));

				switch(type)
				{
					case TS2T_PING:
						break;
					case TS2T_PINGREPLY:
						proto_tree_add_item(ts2_tree, hf_ts2_ackto, tvb, 20, 4, TRUE);
						break;
					case TS2T_LOGINREQUEST:
						proto_tree_add_item(ts2_tree, hf_ts2_protocol_string, tvb, 20, 1, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_platform_string, tvb, 50, 1, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, 80, 9, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_registeredlogin, tvb, 90, 1, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_name, tvb, 90, 1, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_password, tvb, 120, 1, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_nick, tvb, 150, 1, TRUE);

						conversation_data->server_port=pinfo->destport;
						conversation_data->server_addr=pinfo->dst;

						break;
					case TS2T_LOGINREPLY:
						proto_tree_add_item(ts2_tree, hf_ts2_server_name, tvb, 20, 1, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_platform_string, tvb, 50, 1, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, 80, 9, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_badlogin, tvb, 89, 3, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, 92, 80, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_sessionkey, tvb, 172, 4, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_unknown, tvb, 178, 3, TRUE);
						proto_tree_add_item(ts2_tree, hf_ts2_server_welcome_message, tvb, 180, 1, TRUE);
                                                break;
				}
				break;
			case TS2C_ACK:
				/* Ignore the type for ACK, its always zero and clashes with CELP_5_1 */

				proto_tree_add_item(ts2_tree, hf_ts2_seqnum, tvb, 12, 4, TRUE);
				break;
			case TS2C_STANDARD:
				ts2_standard_dissect(tvb, pinfo, ts2_tree, conversation_data);
				break;
		}
	} /* if (tree) */
}
Exemple #27
0
static void
dissect_ftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    gboolean        is_request;
    proto_tree     *ftp_tree;
    proto_tree     *reqresp_tree;
    proto_item     *ti, *hidden_item;
    gint            offset;
    const guchar   *line;
    guint32         code;
    gchar           code_str[4];
    gboolean        is_port_request   = FALSE;
    gboolean        is_eprt_request   = FALSE;
    gboolean        is_pasv_response  = FALSE;
    gboolean        is_epasv_response = FALSE;
    gint            next_offset;
    int             linelen;
    int             tokenlen          = 0;
    const guchar   *next_token;
    guint32         pasv_ip;
    guint32         pasv_offset;
    guint32         ftp_ip;
    guint32         ftp_ip_len;
    guint32         eprt_offset;
    guint32         eprt_af           = 0;
    guint32         eprt_ip;
    guint16         eprt_ipv6[8];
    guint32         eprt_ip_len       = 0;
    guint16         ftp_port;
    guint32         ftp_port_len;
    address         ftp_ip_address;
    gboolean        ftp_nat;
    conversation_t *conversation;

    ftp_ip_address = pinfo->src;

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

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

    /*
     * Find the end of the first 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, 0, -1, &next_offset, FALSE);
    line    = tvb_get_ptr(tvb, 0, linelen);

    /*
     * Put the first line from the buffer into the summary
     * (but leave out the line terminator).
     */
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
        is_request ? "Request" : "Response",
        format_text(line, linelen));

    ti = proto_tree_add_item(tree, proto_ftp, tvb, 0, -1, ENC_NA);
    ftp_tree = proto_item_add_subtree(ti, ett_ftp);

    if (is_request) {
        hidden_item = proto_tree_add_boolean(ftp_tree,
                hf_ftp_request, tvb, 0, 0, TRUE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
        hidden_item = proto_tree_add_boolean(ftp_tree,
                hf_ftp_response, tvb, 0, 0, FALSE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
    } else {
        hidden_item = proto_tree_add_boolean(ftp_tree,
                hf_ftp_request, tvb, 0, 0, FALSE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
        hidden_item = proto_tree_add_boolean(ftp_tree,
                hf_ftp_response, tvb, 0, 0, TRUE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
    }

    /* Put the line into the protocol tree. */
    ti = proto_tree_add_format_text(ftp_tree, tvb, 0, next_offset);
    reqresp_tree = proto_item_add_subtree(ti, ett_ftp_reqresp);

    if (is_request) {
        /*
         * Extract the first token, and, if there is a first
         * token, add it as the request.
         */
        tokenlen = get_token_len(line, line + linelen, &next_token);
        if (tokenlen != 0) {
            proto_tree_add_item(reqresp_tree, hf_ftp_request_command,
                    tvb, 0, tokenlen, ENC_ASCII|ENC_NA);
            if (strncmp(line, "PORT", tokenlen) == 0)
                is_port_request = TRUE;
            /*
             * EPRT request command, as per RFC 2428
             */
            else if (strncmp(line, "EPRT", tokenlen) == 0)
                is_eprt_request = TRUE;
        }
    } else {
        /*
         * This is a response; the response code is 3 digits,
         * followed by a space or hyphen, possibly followed by
         * text.
         *
         * If the line doesn't start with 3 digits, it's part of
         * a continuation.
         *
         * XXX - keep track of state in the first pass, and
         * treat non-continuation lines not beginning with digits
         * as errors?
         */
        if (linelen >= 3 && g_ascii_isdigit(line[0]) && g_ascii_isdigit(line[1])
            && g_ascii_isdigit(line[2])) {
            /*
             * One-line reply, or first or last line
             * of a multi-line reply.
             */
            tvb_get_nstringz0(tvb, 0, sizeof(code_str), code_str);
            code = (guint32)strtoul(code_str, NULL, 10);

            proto_tree_add_uint(reqresp_tree,
                    hf_ftp_response_code, tvb, 0, 3, code);

            /*
             * See if it's a passive-mode response.
             *
             * XXX - does anybody do FOOBAR, as per RFC
             * 1639, or has that been supplanted by RFC 2428?
             */
            if (code == 227)
                is_pasv_response = TRUE;

            /*
             * Responses to EPSV command, as per RFC 2428
             */
            if (code == 229)
                is_epasv_response = TRUE;

            /*
             * Skip the 3 digits and, if present, the
             * space or hyphen.
             */
            if (linelen >= 4)
                next_token = line + 4;
            else
                next_token = line + linelen;
        } else {
            /*
             * Line doesn't start with 3 digits; assume it's
             * a line in the middle of a multi-line reply.
             */
            next_token = line;
        }
    }

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

    /*
     * Add the rest of the first line as request or
     * reply data.
     */
    if (linelen != 0) {
        if (is_request) {
            proto_tree_add_item(reqresp_tree,
                    hf_ftp_request_arg, tvb, offset,
                    linelen, ENC_ASCII|ENC_NA);
        } else {
            proto_tree_add_item(reqresp_tree,
                    hf_ftp_response_arg, tvb, offset,
                    linelen, ENC_ASCII|ENC_NA);
        }
    }
    offset = next_offset;

    /*
     * If this is a PORT request or a PASV response, handle it.
     */
    if (is_port_request) {
        if (parse_port_pasv(line, linelen, &ftp_ip, &ftp_port, &pasv_offset, &ftp_ip_len, &ftp_port_len)) {
            proto_tree_add_ipv4(reqresp_tree, hf_ftp_active_ip,
                    tvb, pasv_offset + (tokenlen+1) , ftp_ip_len, ftp_ip);
            proto_tree_add_uint(reqresp_tree, hf_ftp_active_port,
                    tvb, pasv_offset + 1 + (tokenlen+1) + ftp_ip_len, ftp_port_len, ftp_port);
            SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4, (const guint8 *)&ftp_ip);
            ftp_nat = !ADDRESSES_EQUAL(&pinfo->src, &ftp_ip_address);
            if (ftp_nat) {
                proto_tree_add_boolean(reqresp_tree, hf_ftp_active_nat,
                        tvb, 0, 0, ftp_nat);
            }
        }
    }

    if (is_pasv_response) {
        if (linelen != 0) {
            /*
             * This frame contains a PASV response; set up a
             * conversation for the data.
             */
            if (parse_port_pasv(line, linelen, &pasv_ip, &ftp_port, &pasv_offset, &ftp_ip_len, &ftp_port_len)) {
                proto_tree_add_ipv4(reqresp_tree, hf_ftp_pasv_ip,
                        tvb, pasv_offset + 4, ftp_ip_len, pasv_ip);
                proto_tree_add_uint(reqresp_tree, hf_ftp_pasv_port,
                        tvb, pasv_offset + 4 + 1 + ftp_ip_len, ftp_port_len, ftp_port);
                SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4,
                    (const guint8 *)&pasv_ip);
                ftp_nat = !ADDRESSES_EQUAL(&pinfo->src, &ftp_ip_address);
                if (ftp_nat) {
                    proto_tree_add_boolean(reqresp_tree, hf_ftp_pasv_nat,
                            tvb, 0, 0, ftp_nat);
                }

                /*
                 * We use "ftp_ip_address", so that if
                 * we're NAT'd we look for the un-NAT'd
                 * connection.
                 *
                 * XXX - should this call to
                 * "find_conversation()" just use
                 * "ftp_ip_address" and "server_port", and
                 * wildcard everything else?
                 */
                conversation = find_conversation(pinfo->fd->num, &ftp_ip_address,
                    &pinfo->dst, PT_TCP, ftp_port, 0,
                    NO_PORT_B);
                if (conversation == NULL) {
                    /*
                     * XXX - should this call to "conversation_new()"
                     * just use "ftp_ip_address" and "server_port",
                     * and wildcard everything else?
                     *
                     * XXX - what if we did find a conversation?  As
                     * we create it only on the first pass through the
                     * packets, if we find one, it's presumably an
                     * unrelated conversation.  Should we remove the
                     * old one from the hash table and put this one in
                     * its place?  Can the conversation code handle
                     * conversations not in the hash table?  Or should
                     * we make conversations support start and end
                     * frames, as circuits do, and treat this as an
                     * indication that one conversation was closed and
                     * a new one was opened?
                     */
                    conversation = conversation_new(
                        pinfo->fd->num, &ftp_ip_address, &pinfo->dst,
                        PT_TCP, ftp_port, 0, NO_PORT2);
                    conversation_set_dissector(conversation, ftpdata_handle);
                }
            }
        }
    }

    if (is_eprt_request) {
        /*
         * RFC2428 - sect. 2
         * This frame contains a EPRT request; let's dissect it and set up a
         * conversation for the data connection.
         */
        if (parse_eprt_request(line, linelen,
                    &eprt_af, &eprt_ip, eprt_ipv6, &ftp_port,
                    &eprt_ip_len, &ftp_port_len)) {

            /* since parse_eprt_request() returned TRUE,
               we know that we have a valid address family */
            eprt_offset = tokenlen + 1 + 1;  /* token, space, 1st delimiter */
            proto_tree_add_uint(reqresp_tree, hf_ftp_eprt_af, tvb,
                    eprt_offset, 1, eprt_af);
            eprt_offset += 1 + 1; /* addr family, 2nd delimiter */

            if (eprt_af == EPRT_AF_IPv4) {
                proto_tree_add_ipv4(reqresp_tree, hf_ftp_eprt_ip,
                        tvb, eprt_offset, eprt_ip_len, eprt_ip);
                SET_ADDRESS(&ftp_ip_address, AT_IPv4, 4,
                        (const guint8 *)&eprt_ip);
            }
            else if (eprt_af == EPRT_AF_IPv6) {
                proto_tree_add_ipv6(reqresp_tree, hf_ftp_eprt_ipv6,
                        tvb, eprt_offset, eprt_ip_len, (const guint8 *)eprt_ipv6);
                SET_ADDRESS(&ftp_ip_address, AT_IPv6, 16,
                        (const guint8 *)&eprt_ipv6);
            }
            eprt_offset += eprt_ip_len + 1; /* addr, 3rd delimiter */

            proto_tree_add_uint(reqresp_tree, hf_ftp_eprt_port,
                    tvb, eprt_offset, ftp_port_len, ftp_port);

            /* Find/create conversation for data */
            conversation = find_conversation(pinfo->fd->num,
                    &pinfo->src, &ftp_ip_address,
                    PT_TCP, ftp_port, 0, NO_PORT_B);
            if (conversation == NULL) {
                conversation = conversation_new(
                        pinfo->fd->num, &pinfo->src, &ftp_ip_address,
                        PT_TCP, ftp_port, 0, NO_PORT2);
                conversation_set_dissector(conversation,
                        ftpdata_handle);
            }
        }
        else {
            proto_item *item;
            item = proto_tree_add_text(reqresp_tree,
                    tvb, offset - linelen - 1, linelen, "Invalid EPRT arguments");
            expert_add_info(pinfo, item, &ei_ftp_eprt_args_invalid);
        }
    }

    if (is_epasv_response) {
        if (linelen != 0) {
            proto_item *addr_it;
            /*
             * RFC2428 - sect. 3
             * This frame contains an  EPSV response; set up a
             * conversation for the data.
             */
            if (parse_extended_pasv_response(line, linelen,
                        &ftp_port, &pasv_offset, &ftp_port_len)) {
                /* Add IP address and port number to tree */

                if (ftp_ip_address.type == AT_IPv4) {
                    guint32 addr;
                    memcpy(&addr, ftp_ip_address.data, 4);
                    addr_it = proto_tree_add_ipv4(reqresp_tree,
                            hf_ftp_epsv_ip, tvb, 0, 0, addr);
                    PROTO_ITEM_SET_GENERATED(addr_it);
                }
                else if (ftp_ip_address.type == AT_IPv6) {
                    addr_it = proto_tree_add_ipv6(reqresp_tree,
                            hf_ftp_epsv_ipv6, tvb, 0, 0,
                            (const guint8*)ftp_ip_address.data);
                    PROTO_ITEM_SET_GENERATED(addr_it);
                }

                proto_tree_add_uint(reqresp_tree,
                        hf_ftp_epsv_port, tvb, pasv_offset + 4,
                        ftp_port_len, ftp_port);

                /* Find/create conversation for data */
                conversation = find_conversation(pinfo->fd->num, &ftp_ip_address,
                                                 &pinfo->dst, PT_TCP, ftp_port, 0,
                                                 NO_PORT_B);
                if (conversation == NULL) {
                    conversation = conversation_new(
                        pinfo->fd->num, &ftp_ip_address, &pinfo->dst,
                        PT_TCP, ftp_port, 0, NO_PORT2);
                    conversation_set_dissector(conversation,
                        ftpdata_handle);
                }
            }
            else {
                proto_item *item;
                item = proto_tree_add_text(reqresp_tree,
                        tvb, offset - linelen - 1, linelen, "Invalid EPSV arguments");
                expert_add_info(pinfo, item, &ei_ftp_epsv_args_invalid);
            }
        }
    }

    /*
     * Show the rest of the request or response as text,
     * a line at a time.
     * XXX - only if there's a continuation indicator?
     */
    while (tvb_offset_exists(tvb, offset)) {
        /*
         * Find the end of the line.
         */
        tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);

        /*
         * Put this line.
         */
        proto_tree_add_format_text(ftp_tree, tvb, offset,
                next_offset - offset);
        offset = next_offset;
    }
}
Exemple #28
0
static void
dissect_ipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	tvbuff_t	*next_tvb;

	proto_tree	*ipx_tree = NULL;
	proto_item	*ti = NULL, *hidden_item;

	const guint8	*src_net_node, *dst_net_node;

	guint8		ipx_hops;
	char 		*str;
	guint16		first_socket, second_socket;
	guint32		ipx_snet, ipx_dnet;
	static ipxhdr_t ipxh_arr[4];
	static int ipx_current=0;
	ipxhdr_t *ipxh;

	ipx_current++;
	if(ipx_current==4){
		ipx_current=0;
	}
	ipxh=&ipxh_arr[ipx_current];


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

	/* Calculate here for use in pinfo and in tree */
	ipxh->ipx_dsocket = tvb_get_ntohs(tvb, 16);
	ipxh->ipx_ssocket = tvb_get_ntohs(tvb, 28);
	ipxh->ipx_type    = tvb_get_guint8(tvb, 5);
	ipxh->ipx_length  = tvb_get_ntohs(tvb, 2);

	pinfo->ptype = PT_IPX;
	pinfo->srcport = ipxh->ipx_ssocket;
	pinfo->destport = ipxh->ipx_dsocket;

	/* Adjust the tvbuff length to include only the IPX datagram. */
	set_actual_length(tvb, ipxh->ipx_length);

	src_net_node = tvb_get_ptr(tvb, 18, 10);
	dst_net_node = tvb_get_ptr(tvb, 6,  10);

	SET_ADDRESS(&pinfo->net_src,	AT_IPX, 10, src_net_node);
	SET_ADDRESS(&pinfo->src,	AT_IPX, 10, src_net_node);
	SET_ADDRESS(&ipxh->ipx_src,	AT_IPX, 10, src_net_node);
	SET_ADDRESS(&pinfo->net_dst,	AT_IPX, 10, dst_net_node);
	SET_ADDRESS(&pinfo->dst,	AT_IPX, 10, dst_net_node);
	SET_ADDRESS(&ipxh->ipx_dst,	AT_IPX, 10, dst_net_node);

	if (check_col(pinfo->cinfo, COL_INFO))
		col_add_fstr(pinfo->cinfo, COL_INFO, "%s (0x%04x)",
				socket_text(ipxh->ipx_dsocket), ipxh->ipx_dsocket);

	if (tree) {

		ti = proto_tree_add_item(tree, proto_ipx, tvb, 0, IPX_HEADER_LEN, ENC_NA);
		ipx_tree = proto_item_add_subtree(ti, ett_ipx);
	}

	str=ep_address_to_str(&pinfo->net_src);
	hidden_item = proto_tree_add_string(ipx_tree, hf_ipx_src, tvb, 0, 0, str);
	PROTO_ITEM_SET_HIDDEN(hidden_item);
	hidden_item = proto_tree_add_string(ipx_tree, hf_ipx_addr, tvb, 0, 0, str);
	PROTO_ITEM_SET_HIDDEN(hidden_item);
	str=ep_address_to_str(&pinfo->net_dst);
	hidden_item = proto_tree_add_string(ipx_tree, hf_ipx_dst, tvb, 0, 0, str);
	PROTO_ITEM_SET_HIDDEN(hidden_item);
	hidden_item = proto_tree_add_string(ipx_tree, hf_ipx_addr, tvb, 0, 0, str);
	PROTO_ITEM_SET_HIDDEN(hidden_item);

	proto_tree_add_item(ipx_tree, hf_ipx_checksum, tvb, 0, 2, ENC_BIG_ENDIAN);
	proto_tree_add_uint_format(ipx_tree, hf_ipx_len, tvb, 2, 2, ipxh->ipx_length,
		"Length: %d bytes", ipxh->ipx_length);
	ipx_hops = tvb_get_guint8(tvb, 4);
	proto_tree_add_uint_format(ipx_tree, hf_ipx_hops, tvb, 4, 1, ipx_hops,
		"Transport Control: %d hops", ipx_hops);
	proto_tree_add_uint(ipx_tree, hf_ipx_packet_type, tvb, 5, 1, ipxh->ipx_type);

	/* Destination */
	ipx_dnet = tvb_get_ntohl(tvb, 6);
	proto_tree_add_ipxnet(ipx_tree, hf_ipx_dnet, tvb, 6, 4,
		ipx_dnet);
	hidden_item = proto_tree_add_ipxnet(ipx_tree, hf_ipx_net, tvb, 6, 4,
		ipx_dnet);
	PROTO_ITEM_SET_HIDDEN(hidden_item);
	proto_tree_add_item(ipx_tree, hf_ipx_dnode, tvb, 10, 6, ENC_NA);
	hidden_item = proto_tree_add_item(ipx_tree, hf_ipx_node, tvb, 10, 6, ENC_NA);
	PROTO_ITEM_SET_HIDDEN(hidden_item);
	proto_tree_add_uint(ipx_tree, hf_ipx_dsocket, tvb, 16, 2,
		ipxh->ipx_dsocket);
	hidden_item = proto_tree_add_uint(ipx_tree, hf_ipx_socket, tvb, 16, 2,
		ipxh->ipx_dsocket);
	PROTO_ITEM_SET_HIDDEN(hidden_item);

	/* Source */
	ipx_snet = tvb_get_ntohl(tvb, 18);
	proto_tree_add_ipxnet(ipx_tree, hf_ipx_snet, tvb, 18, 4,
		ipx_snet);
	hidden_item = proto_tree_add_ipxnet(ipx_tree, hf_ipx_net, tvb, 18, 4,
		ipx_snet);
	PROTO_ITEM_SET_HIDDEN(hidden_item);
	proto_tree_add_item(ipx_tree, hf_ipx_snode, tvb, 22, 6, ENC_NA);
	hidden_item = proto_tree_add_item(ipx_tree, hf_ipx_node, tvb, 22, 6, ENC_NA);
	PROTO_ITEM_SET_HIDDEN(hidden_item);
	proto_tree_add_uint(ipx_tree, hf_ipx_ssocket, tvb, 28, 2,
		ipxh->ipx_ssocket);
	hidden_item = proto_tree_add_uint(ipx_tree, hf_ipx_socket, tvb, 28, 2,
		ipxh->ipx_ssocket);
	PROTO_ITEM_SET_HIDDEN(hidden_item);

	/* Make the next tvbuff */
	next_tvb = tvb_new_subset_remaining(tvb, IPX_HEADER_LEN);

	/*
	 * Let the subdissector know what type of IPX packet this is.
	 */
	pinfo->ipxptype = ipxh->ipx_type;

	/*
	 * Check the socket numbers before we check the packet type;
	 * we've seen non-NCP packets with a type of NCP and a
	 * destination socket of IPX_SOCKET_IPX_MESSAGE, and SAP
	 * packets with a type of NCP and a destination socket of
	 * IPX_SOCKET_SAP.
	 *
	 * We've seen NCP packets with a type of NCP, a source socket of
	 * IPX_SOCKET_NCP, and a destination socket of IPX_SOCKET_IPX_MESSAGE,
	 * and we've seen NCP packets with a type of NCP, a source socket of
	 * IPX_SOCKET_IPX_MESSAGE, and a destination socket of
	 * IPX_SOCKET_NCP, so testing the destination socket first doesn't
	 * always give the right answer.  We've also seen SAP packets with
	 * a source socket of IPX_SOCKET_SAP and a destination socket of
	 * IPX_SOCKET_IPX_MESSAGE.
	 *
	 * Unfortunately, we've also seen packets with a source socket
	 * of IPX_SOCKET_NWLINK_SMB_SERVER and a destination socket
	 * of IPX_SOCKET_NWLINK_SMB_NAMEQUERY that were NMPI packets,
	 * not SMB packets, so testing the lower-valued socket first
	 * also doesn't always give the right answer.
	 *
	 * So we start out assuming we should test the lower-numbered
	 * socket number first, but, if the higher-numbered socket is
	 * IPX_SOCKET_NWLINK_SMB_NAMEQUERY, we assume that it's a
	 * NMPI query, and test only that socket.
	 */
	if (ipxh->ipx_ssocket > ipxh->ipx_dsocket) {
		first_socket = ipxh->ipx_dsocket;
		second_socket = ipxh->ipx_ssocket;
	} else {
		first_socket = ipxh->ipx_ssocket;
		second_socket = ipxh->ipx_dsocket;
	}

	tap_queue_packet(ipx_tap, pinfo, ipxh);

	if (second_socket != IPX_SOCKET_NWLINK_SMB_NAMEQUERY) {
		if (dissector_try_uint(ipx_socket_dissector_table, first_socket,
		    next_tvb, pinfo, tree))
			return;
	}
	if (dissector_try_uint(ipx_socket_dissector_table, second_socket,
	    next_tvb, pinfo, tree))
		return;

	/*
	 * Neither of them are known; try the packet type, which will
	 * at least let us, for example, dissect SPX packets as SPX.
	 */
	if (dissector_try_uint(ipx_type_dissector_table, ipxh->ipx_type, next_tvb,
	    pinfo, tree))
		return;

	call_dissector(data_handle,next_tvb, pinfo, tree);
}
Exemple #29
0
static void
dissect_cmstatus (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
{
  proto_item *it;
  proto_tree *cmstatus_tree = NULL;
  guint16 transid;
  guint8 event_type;
  guint16 len;
  transid = tvb_get_ntohs (tvb, 0);
  event_type = tvb_get_guint8 (tvb, 2);
  len = tvb_reported_length_remaining (tvb, 3);
  col_clear (pinfo->cinfo, COL_INFO);
  col_add_fstr (pinfo->cinfo, COL_INFO, "CM-STATUS Report: Transaction ID = %u", transid);

  if (tree)
  {
    it = proto_tree_add_protocol_format (tree, proto_docsis_cmstatus, tvb, 0, -1, "CM-STATUS Report");
    cmstatus_tree = proto_item_add_subtree (it, ett_docsis_cmstatus);
    proto_tree_add_item (cmstatus_tree, hf_docsis_cmstatus_tranid, tvb, 0, 2, ENC_BIG_ENDIAN);

    switch (event_type)
    {
    case SEC_CH_MDD_TIMEOUT:
      proto_tree_add_item (cmstatus_tree, hf_docsis_cmstatus_e_t_mdd_t, tvb, 2, 1, ENC_BIG_ENDIAN);
      break;

    case QAM_FEC_LOCK_FAILURE:
      proto_tree_add_item (cmstatus_tree, hf_docsis_cmstatus_e_t_qfl_f, tvb, 2, 1, ENC_BIG_ENDIAN);
      break;

    case SEQ_OUT_OF_RANGE:
      proto_tree_add_item (cmstatus_tree, hf_docsis_cmstatus_e_t_s_o, tvb, 2, 1, ENC_BIG_ENDIAN);
      break;

    case SEC_CH_MDD_RECOVERY:
      proto_tree_add_item (cmstatus_tree, hf_docsis_cmstatus_e_t_mdd_r, tvb, 2, 1, ENC_BIG_ENDIAN);
      break;

    case QAM_FEC_LOCK_RECOVERY:
      proto_tree_add_item (cmstatus_tree, hf_docsis_cmstatus_e_t_qfl_r, tvb, 2, 1, ENC_BIG_ENDIAN);
      break;

    case T4_TIMEOUT:
      proto_tree_add_item (cmstatus_tree, hf_docsis_cmstatus_e_t_t4_t, tvb, 2, 1, ENC_BIG_ENDIAN);
      break;

    case T3_RETRIES_EXCEEDED:
      proto_tree_add_item (cmstatus_tree, hf_docsis_cmstatus_e_t_t3_e, tvb, 2, 1, ENC_BIG_ENDIAN);
      break;

    case SUCCESS_RANGING_AFTER_T3_RETRIES_EXCEEDED:
      proto_tree_add_item (cmstatus_tree, hf_docsis_cmstatus_e_t_rng_s, tvb, 2, 1, ENC_BIG_ENDIAN);
      break;

    case CM_ON_BATTERY:
      proto_tree_add_item (cmstatus_tree, hf_docsis_cmstatus_e_t_cm_b, tvb, 2, 1, ENC_BIG_ENDIAN);
      break;

    case CM_ON_AC_POWER:
      proto_tree_add_item (cmstatus_tree, hf_docsis_cmstatus_e_t_cm_a, tvb, 2, 1, ENC_BIG_ENDIAN);
      break;
    } /* switch */

  }
    /* Call Dissector TLV's */
  dissect_cmstatus_tlv(tvb, cmstatus_tree, 3, len);
}
static void
dissect_ppi_gps(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
    /* These are locals used for processing the current tvb */
    guint length;
    gint  length_remaining;
    int offset = 0;

    proto_tree *ppi_gps_tree = NULL;
    proto_tree *pt, *present_tree = NULL;
    proto_tree *my_pt, *gpsflags_flags_tree = NULL; /* used for DeviceType bitmask stuff */

    proto_item *ti = NULL;
    proto_item *gps_line = NULL;


    /* bits */
    int bit;
    guint32 present, next_present;
    /* values actually read out, for displaying */
    guint32 version, gpsflags_flags;
    gdouble lat, lon, alt, alt_gnd;
    nstime_t gps_timestamp;
    int gps_time_size, already_processed_fractime; /* we use this internally to track if this is a 4 or 8 byte wide timestamp */
    gdouble eph, epv, ept;
    gchar *curr_str;


    /* these are temporary intermediate values, used in the individual cases below */
    guint32 t_lat, t_lon, t_alt, t_alt_gnd;
    guint32 t_herr, t_verr, t_terr;
    guint32 t_appspecific_num;
    /* initialize the timestamp value(s) */
    gps_timestamp.secs = gps_timestamp.nsecs = already_processed_fractime = 0;

    /* Clear out stuff in the info column */
    col_clear(pinfo->cinfo,COL_INFO);

    /* pull out the first three fields of the BASE-GEOTAG-HEADER */
    version = tvb_get_guint8(tvb, offset);
    length  = tvb_get_letohs(tvb, offset+2);
    present = tvb_get_letohl(tvb, offset+4);

    /* Setup basic column info */
    if (check_col(pinfo->cinfo, COL_INFO))
        col_add_fstr(pinfo->cinfo, COL_INFO, "PPI_GPS Capture v%u, Length %u", version, length);

    /* Create the basic dissection tree*/
    if (tree) {
        ti = proto_tree_add_protocol_format(tree, proto_ppi_gps, tvb, 0, length, "GPS:");
        gps_line = ti; /*we will make this more useful if we hit lon/lat later */
        ppi_gps_tree= proto_item_add_subtree(ti, ett_ppi_gps);
        proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_version, tvb, offset, 1, version);
        proto_tree_add_item(ppi_gps_tree, hf_ppi_gps_pad, tvb, offset + 1, 1, ENC_NA);
        ti = proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_length, tvb, offset + 2, 2, length);
    }

    /* We support v1 and v2 of GPS tags (identical) */
    if (! (version == 1 || version == 2) ) {
        if (tree)
            proto_item_append_text(ti, "invalid version (got %d,  expected 1 or 2)", version);
        return;
    }

    /* initialize the length of the actual tag contents */
    length_remaining = length;
    /* minimum length check, should atleast be a fixed-size geotagging-base header*/
    if (length_remaining < PPI_GEOBASE_MIN_HEADER_LEN) {
        /*
         * Base-geotag-header (Radiotap lookalike) is shorter than the fixed-length portion
         * plus one "present" bitset.
         */
        if (tree)
            proto_item_append_text(ti, " (invalid - minimum length is 8)");
        return;
    }

    /* perform tag-specific max length sanity checking */
    if (length > PPI_GPS_MAXTAGLEN ) {
        if (tree)
            proto_item_append_text(ti, "Invalid PPI-GPS length  (got %d, %d max\n)", length, PPI_GPS_MAXTAGLEN);
        return;
    }

    /* Subtree for the "present flags" bitfield. */
    if (tree) {
        pt = proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_present, tvb, offset + 4, 4, present);
        present_tree = proto_item_add_subtree(pt, ett_ppi_gps_present);

        proto_tree_add_item(present_tree, hf_ppi_gps_present_gpsflags_flags, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_lat, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_lon, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_alt, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_alt_gnd, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_gpstime, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_fractime, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_eph, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_epv, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_ept, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_descr, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_appspecific_num, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_appspecific_data, tvb, 4, 4, ENC_LITTLE_ENDIAN);
        proto_tree_add_item(present_tree, hf_ppi_gps_present_ext, tvb, 4, 4, ENC_LITTLE_ENDIAN);
    }
    offset += PPI_GEOBASE_MIN_HEADER_LEN;
    length_remaining -= PPI_GEOBASE_MIN_HEADER_LEN;

    /* The fixed BASE-GEOTAG-HEADER has been handled at this point. move on to the individual fields */
    for (; present; present = next_present) {
        /* clear the least significant bit that is set */
        next_present = present & (present - 1);
        /* extract the least significant bit that is set */
        bit = BITNO_32(present ^ next_present);
        switch (bit) {
        case PPI_GEOTAG_GPSFLAGS:
            if (length_remaining < 4)
                break;
            gpsflags_flags =   tvb_get_letohl(tvb, offset); /* retrieve 32-bit gpsflags bitmask (-not- present bitmask) */
            if (tree) {
                /* first we add the hex flags line */
                my_pt = proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_gpsflags_flags, tvb, offset , 4, gpsflags_flags);
                /* then we add a subtree */
                gpsflags_flags_tree = proto_item_add_subtree(my_pt, ett_ppi_gps_gpsflags_flags);
                /* to pin the individual bits on */
                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag0_nofix, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag1_gpsfix, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag2_diffgps, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag3_PPS, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag4_RTK, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag5_floatRTK, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag6_dead_reck, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag7_manual, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(gpsflags_flags_tree, hf_ppi_gps_gpsflags_flag8_sim, tvb, offset, 4, ENC_LITTLE_ENDIAN);
            }
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_GEOTAG_LAT:
            if (length_remaining < 4)
                break;
            t_lat = tvb_get_letohl(tvb, offset);
            lat =  ppi_fixed3_7_to_gdouble(t_lat);
            if (tree)
            {
                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_lat, tvb, offset, 4, lat);
                proto_item_append_text(gps_line, " Lat:%f ", lat);
            }
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_GEOTAG_LON:
            if (length_remaining < 4)
                break;
            t_lon = tvb_get_letohl(tvb, offset);
            lon =  ppi_fixed3_7_to_gdouble(t_lon);
            if (tree)
            {
                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_lon, tvb, offset, 4, lon);
                proto_item_append_text(gps_line, " Lon:%f ", lon);
            }
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_GEOTAG_ALT:
            if (length_remaining < 4)
                break;
            t_alt = tvb_get_letohl(tvb, offset);
            alt = ppi_fixed6_4_to_gdouble(t_alt);
            if (tree)
            {
                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_alt, tvb, offset, 4, alt);
                proto_item_append_text(gps_line, " Alt:%f ", alt);
            }
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_GEOTAG_ALT_G:
            if (length_remaining < 4)
                break;
            t_alt_gnd = tvb_get_letohl(tvb, offset);
            alt_gnd = ppi_fixed6_4_to_gdouble(t_alt_gnd);
            if (tree)
            {
                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_alt_gnd, tvb, offset, 4, alt_gnd);
                proto_item_append_text(gps_line, " Alt_g:%f ", alt_gnd);
            }
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_GEOTAG_GPSTIME:
            if (length_remaining < 4)
                break;
            gps_timestamp.secs =    tvb_get_letohl(tvb, offset);
            gps_timestamp.nsecs = 0;
            gps_time_size = 4;
            /* This is somewhat tricky, inside the GPSTIME case we test if the optional fractional time */
            /* is present. If so, we pull it out, and combine it with GPSTime. */
            /* If we do this, we set already_processed_fractime to avoid hitting it below */
            if (length_remaining < 4 && (present & PPI_GPS_MASK_FRACTIME))
                break;
            else if (present & PPI_GPS_MASK_FRACTIME) {
                gps_timestamp.nsecs =  tvb_get_letohl(tvb, offset + 4); /* manually offset seconds */
                already_processed_fractime = 1;
                gps_time_size = 8;
            }
            if (tree) {
                proto_tree_add_time(ppi_gps_tree, hf_ppi_gps_gpstime, tvb, offset, gps_time_size, &gps_timestamp);
            }
            offset += gps_time_size;
            length_remaining -= gps_time_size;
            break;
        case  PPI_GEOTAG_FRACTIONALTIME:
            if (length_remaining < 4)
                break;
            if (already_processed_fractime)
                break;
            break;
        case  PPI_GEOTAG_EPH:
            if (length_remaining < 4)
                break;
            t_herr = tvb_get_letohl(tvb, offset);
            eph  =  ppi_fixed3_6_to_gdouble(t_herr);
            if (tree)
                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_eph, tvb, offset, 4, eph);
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_GEOTAG_EPV:
            if (length_remaining < 4)
                break;
            t_verr = tvb_get_letohl(tvb, offset);
            epv  =  ppi_fixed3_6_to_gdouble(t_verr);
            if (tree)
                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_epv, tvb, offset, 4, epv);
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_GEOTAG_EPT:
            if (length_remaining < 4)
                break;
            t_terr = tvb_get_letohl(tvb, offset);
            ept  =  ppi_ns_counter_to_gdouble(t_terr);
            if (tree)
                proto_tree_add_double(ppi_gps_tree, hf_ppi_gps_ept, tvb, offset, 4, ept);
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_GEOTAG_DESCRIPTIONSTR:
            if (length_remaining < 32)
                break;
            if (tree)
            {
                /* proto_tree_add_item(ppi_gps_tree, hf_ppi_gps_descstr, tvb, offset, 32,  ENC_ASCII|ENC_NA); */
                curr_str = tvb_format_stringzpad(tvb, offset, 32); /* need to append_text this */
                proto_tree_add_string(ppi_gps_tree, hf_ppi_gps_descstr, tvb, offset, 32, curr_str);
                proto_item_append_text(gps_line, " (%s)", curr_str);
            }
            offset+=32;
            length_remaining-=32;
            break;
        case  PPI_GEOTAG_APPID:
            if (length_remaining < 4)
                break;
            t_appspecific_num  = tvb_get_letohl(tvb, offset); /* application specific parsers may switch on this later */
            if (tree) {
                proto_tree_add_uint(ppi_gps_tree, hf_ppi_gps_appspecific_num, tvb, offset, 4, t_appspecific_num);
            }
            offset+=4;
            length_remaining-=4;
            break;
        case  PPI_GEOTAG_APPDATA:
            if (length_remaining < 60)
                break;
            if (tree) {
                proto_tree_add_item(ppi_gps_tree, hf_ppi_gps_appspecific_data, tvb, offset, 60,  ENC_NA);
            }
            offset+=60;
            length_remaining-=60;
            break;

            /*
             * This indicates a field whose size we do not know, so we cannot proceed.
             */
        default:
            next_present = 0; /* this will terminate the loop */
            proto_tree_add_text(ppi_gps_tree, tvb, offset, 0,  "Error: PPI-GEOLOCATION-GPS: unknown bit (%d) set in present field.\n", bit);
            continue;
        } /* switch (bit) */

    } /* (for present..)*/

    /* If there was any post processing of the elements, it could happen here. */
    return;
}