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_format_text(acap_tree, 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.
		 */
	}
}
Beispiel #2
0
static void
dissect_icap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*icap_tree = NULL;
	proto_item	*ti = NULL;
	proto_item	*hidden_item;
	gint		offset = 0;
	const guchar	*line;
	gint		next_offset;
	const guchar	*linep, *lineend;
	int		linelen;
	guchar		c;
	icap_type_t     icap_type;
	int		datalen;

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

	/*
	 * Put the first line from the buffer into the summary
	 * if it's an ICAP header (but leave out the
	 * line terminator).
	 * Otherwise, just call it a continuation.
	 *
	 * Note that "tvb_find_line_end()" will return a value that
	 * is not longer than what's in the buffer, so the
	 * "tvb_get_ptr()" call won't throw an exception.
	 */
	linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
	line = tvb_get_ptr(tvb, offset, linelen);
	icap_type = ICAP_OTHER;	/* type not known yet */
	if (is_icap_message(line, linelen, &icap_type))
		col_add_str(pinfo->cinfo, COL_INFO,
		    format_text(line, linelen));
	else
		col_set_str(pinfo->cinfo, COL_INFO, "Continuation");

	if (tree) {
		ti = proto_tree_add_item(tree, proto_icap, tvb, offset, -1,
		    ENC_NA);
		icap_tree = proto_item_add_subtree(ti, ett_icap);
	}

	/*
	 * Process the packet data, a line at a time.
	 */
	icap_type = ICAP_OTHER;	/* type not known yet */
	while (tvb_offset_exists(tvb, offset)) {
		gboolean is_icap = FALSE;
		gboolean loop_done = FALSE;
		/*
		 * Find the end of the line.
		 */
		linelen = tvb_find_line_end(tvb, offset, -1, &next_offset,
		    FALSE);

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

		/*
		 * find header format
		 */
		if (is_icap_message(line, linelen, &icap_type)) {
			goto is_icap_header;
		}

		/*
		 * if it looks like a blank line, end of header perhaps?
		 */
		if (linelen == 0) {
			goto is_icap_header;
		}

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

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

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

			switch (c) {

			case '(':
			case ')':
			case '<':
			case '>':
			case '@':
			case ',':
			case ';':
			case '\\':
			case '"':
			case '/':
			case '[':
			case ']':
			case '?':
			case '=':
			case '{':
			case '}':
				/*
				 * It's a separator, so it's not part of a
				 * token, so it's not a field name for the
				 * beginning of a header.
				 *
				 * (We don't have to check for HT; that's
				 * already been ruled out by "iscntrl()".)
				 *
				 * XXX - what about ' '?  HTTP's checks
				 * check for that.
				 */
				is_icap = FALSE;
				loop_done = TRUE;
				break;

			case ':':
				/*
				 * This ends the token; we consider this
				 * to be a header.
				 */
				goto is_icap_header;
			}
		}

		/*
		 * We don't consider this part of an ICAP message,
		 * so we don't display it.
		 * (Yeah, that means we don't display, say, a text/icap
		 * page, but you can get that from the data pane.)
		 */
		if (!is_icap)
			break;
is_icap_header:
		if (tree) {
			proto_tree_add_text(icap_tree, tvb, offset,
				next_offset - offset, "%s",
				tvb_format_text(tvb, offset,
						next_offset - offset)
				);
		}
		offset = next_offset;
	}

	if (tree) {
		switch (icap_type) {

		case ICAP_OPTIONS:
			hidden_item = proto_tree_add_boolean(icap_tree,
					    hf_icap_options, tvb, 0, 0, 1);
                        PROTO_ITEM_SET_HIDDEN(hidden_item);
			break;

		case ICAP_REQMOD:
			hidden_item = proto_tree_add_boolean(icap_tree,
					    hf_icap_reqmod, tvb, 0, 0, 1);
                        PROTO_ITEM_SET_HIDDEN(hidden_item);
			break;

		case ICAP_RESPMOD:
			hidden_item = proto_tree_add_boolean(icap_tree,
					    hf_icap_respmod, tvb, 0, 0, 1);
                        PROTO_ITEM_SET_HIDDEN(hidden_item);
			break;

		case ICAP_RESPONSE:
			hidden_item = proto_tree_add_boolean(icap_tree,
					    hf_icap_response, tvb, 0, 0, 1);
                        PROTO_ITEM_SET_HIDDEN(hidden_item);
			break;

		case ICAP_OTHER:
		default:
			break;
		}
	}

	datalen = tvb_length_remaining(tvb, offset);
	if (datalen > 0) {
		call_dissector(data_handle,
		    tvb_new_subset_remaining(tvb, offset), pinfo, icap_tree);
	}
}
static void
dissect_fddi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
		gboolean bitswapped)
{
  proto_tree *fh_tree = NULL;
  proto_item *ti, *hidden_item;
  const gchar *fc_str;
  proto_tree *fc_tree;
  static guchar src[6], dst[6];
  guchar     src_swapped[6], dst_swapped[6];
  tvbuff_t   *next_tvb;
  static fddi_hdr fddihdrs[4];
  static int fddihdr_num=0;
  fddi_hdr *fddihdr;

  fddihdr_num++;
  if(fddihdr_num>=4){
     fddihdr_num=0;
  }
  fddihdr=&fddihdrs[fddihdr_num];

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

  fddihdr->fc = tvb_get_guint8(tvb, FDDI_P_FC + FDDI_PADDING);
  fc_str = fddifc_to_str(fddihdr->fc);

  if (check_col(pinfo->cinfo, COL_INFO))
    col_add_str(pinfo->cinfo, COL_INFO, fc_str);

  if (tree) {
    ti = proto_tree_add_protocol_format(tree, proto_fddi, tvb, 0, FDDI_HEADER_SIZE+FDDI_PADDING,
		"Fiber Distributed Data Interface, %s", fc_str);
    fh_tree = proto_item_add_subtree(ti, ett_fddi);
    ti = proto_tree_add_uint_format(fh_tree, hf_fddi_fc, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc,
        "Frame Control: 0x%02x (%s)", fddihdr->fc, fc_str);
    fc_tree = proto_item_add_subtree(ti, ett_fddi_fc);
    proto_tree_add_uint(fc_tree, hf_fddi_fc_clf, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc);
    switch ((fddihdr->fc) & FDDI_FC_CLFF) {

    case FDDI_FC_SMT:
      proto_tree_add_uint(fc_tree, hf_fddi_fc_smt_subtype, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc);
      break;

    case FDDI_FC_MAC:
      if (fddihdr->fc != FDDI_FC_RT)
        proto_tree_add_uint(fc_tree, hf_fddi_fc_mac_subtype, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc);
      break;

    case FDDI_FC_LLC_ASYNC:
      if (!((fddihdr->fc) & FDDI_FC_ASYNC_R))
        proto_tree_add_uint(fc_tree, hf_fddi_fc_prio, tvb, FDDI_P_FC + FDDI_PADDING, 1, fddihdr->fc);
      break;
    }
  }

  /* Extract the destination address, possibly bit-swapping it. */
  if (bitswapped)
    swap_mac_addr(dst, tvb_get_ptr(tvb, FDDI_P_DHOST + FDDI_PADDING, 6));
  else
    memcpy(dst, tvb_get_ptr(tvb, FDDI_P_DHOST + FDDI_PADDING, 6), sizeof dst);
  swap_mac_addr(dst_swapped, tvb_get_ptr(tvb, FDDI_P_DHOST + FDDI_PADDING, 6));

  /* XXX - copy them to some buffer associated with "pi", rather than
     just making "dst" static? */
  SET_ADDRESS(&pinfo->dl_dst, AT_ETHER, 6, &dst[0]);
  SET_ADDRESS(&pinfo->dst, AT_ETHER, 6, &dst[0]);
  SET_ADDRESS(&fddihdr->dst, AT_ETHER, 6, &dst[0]);

  if (fh_tree) {
    proto_tree_add_ether(fh_tree, hf_fddi_dst, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst);
    hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_addr, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst);
    PROTO_ITEM_SET_HIDDEN(hidden_item);

    /* hide some bit-swapped mac address fields in the proto_tree, just in case */
    hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_dst, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst_swapped);
    PROTO_ITEM_SET_HIDDEN(hidden_item);
    hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_addr, tvb, FDDI_P_DHOST + FDDI_PADDING, 6, dst_swapped);
    PROTO_ITEM_SET_HIDDEN(hidden_item);
  }

  /* Extract the source address, possibly bit-swapping it. */
  if (bitswapped)
    swap_mac_addr(src, tvb_get_ptr(tvb, FDDI_P_SHOST + FDDI_PADDING, 6));
  else
    memcpy(src, tvb_get_ptr(tvb, FDDI_P_SHOST + FDDI_PADDING, 6), sizeof src);
  swap_mac_addr(src_swapped, tvb_get_ptr(tvb, FDDI_P_SHOST + FDDI_PADDING, 6));

  /* XXX - copy them to some buffer associated with "pi", rather than
     just making "src" static? */
  SET_ADDRESS(&pinfo->dl_src, AT_ETHER, 6, &src[0]);
  SET_ADDRESS(&pinfo->src, AT_ETHER, 6, &src[0]);
  SET_ADDRESS(&fddihdr->src, AT_ETHER, 6, &src[0]);

  if (fh_tree) {
      proto_tree_add_ether(fh_tree, hf_fddi_src, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src);
      hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_addr, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src);
      PROTO_ITEM_SET_HIDDEN(hidden_item);

      /* hide some bit-swapped mac address fields in the proto_tree, just in case */
      hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_src, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src_swapped);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
      hidden_item = proto_tree_add_ether(fh_tree, hf_fddi_addr, tvb, FDDI_P_SHOST + FDDI_PADDING, 6, src_swapped);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
  }

  next_tvb = tvb_new_subset_remaining(tvb, FDDI_HEADER_SIZE + FDDI_PADDING);


  tap_queue_packet(fddi_tap, pinfo, fddihdr);

  switch (fddihdr->fc) {

    /* From now, only 802.2 SNAP (Async. LCC frame) is supported */

    case FDDI_FC_LLC_ASYNC + 0  :
    case FDDI_FC_LLC_ASYNC + 1  :
    case FDDI_FC_LLC_ASYNC + 2  :
    case FDDI_FC_LLC_ASYNC + 3  :
    case FDDI_FC_LLC_ASYNC + 4  :
    case FDDI_FC_LLC_ASYNC + 5  :
    case FDDI_FC_LLC_ASYNC + 6  :
    case FDDI_FC_LLC_ASYNC + 7  :
    case FDDI_FC_LLC_ASYNC + 8  :
    case FDDI_FC_LLC_ASYNC + 9  :
    case FDDI_FC_LLC_ASYNC + 10 :
    case FDDI_FC_LLC_ASYNC + 11 :
    case FDDI_FC_LLC_ASYNC + 12 :
    case FDDI_FC_LLC_ASYNC + 13 :
    case FDDI_FC_LLC_ASYNC + 14 :
    case FDDI_FC_LLC_ASYNC + 15 :
      call_dissector(llc_handle, next_tvb, pinfo, tree);
      return;

    default :
      call_dissector(data_handle,next_tvb, pinfo, tree);
      return;

  } /* fc */
} /* dissect_fddi */
static void
dissect_nstrace(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree     *ns_tree = NULL, *flagtree = NULL;
	proto_item     *ti = NULL, *flagitem = NULL;
	struct nstr_phdr *pnstr = &(pinfo->pseudo_header->nstr);
	tvbuff_t       *next_tvb_eth_client;
	guint8		offset;
	guint		i, bpos;
	wmem_strbuf_t  *flags_strbuf = wmem_strbuf_new_label(wmem_packet_scope());
	static const gchar *flags[] = {"FP", "FR", "DFD", "SRSS", "RSSH"};
	gboolean 	first_flag = TRUE;
	guint8		flagoffset, flagval;
	guint8		src_vmname_len = 0, dst_vmname_len = 0;
	guint8		variable_ns_len = 0;
	guint 		flagval32;

	wmem_strbuf_append(flags_strbuf, "None");

	if (pnstr->rec_type == NSPR_HEADER_VERSION205)
		{
		src_vmname_len = tvb_get_guint8(tvb,pnstr->src_vmname_len_offset);
		dst_vmname_len = tvb_get_guint8(tvb,pnstr->dst_vmname_len_offset);
		variable_ns_len = src_vmname_len + dst_vmname_len;
		pnstr->eth_offset += variable_ns_len;
		}

	ti = proto_tree_add_protocol_format(tree, proto_nstrace, tvb, 0, pnstr->eth_offset, "NetScaler Packet Trace");
	ns_tree = proto_item_add_subtree(ti, ett_ns);

	proto_tree_add_item(ns_tree, hf_ns_dir, tvb, pnstr->dir_offset, pnstr->dir_len, ENC_LITTLE_ENDIAN);
	proto_tree_add_item(ns_tree, hf_ns_nicno, tvb, pnstr->nicno_offset, pnstr->nicno_len, ENC_LITTLE_ENDIAN);

	switch (pnstr->rec_type)
	{
	case NSPR_HEADER_VERSION206:
		flagoffset = pnstr->ns_activity_offset;
		flagval32 = tvb_get_letohl(tvb, flagoffset);
		flagitem = proto_tree_add_uint_format(ns_tree, hf_ns_activity, tvb, flagoffset, 4, flagval32,
						"Activity Flags: 0x%04x", flagval32);
		flagtree = proto_item_add_subtree(flagitem, ett_ns_activity_flags);
		proto_tree_add_item(flagtree, hf_ns_activity_perf_collection, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(flagtree, hf_ns_activity_pcb_zombie, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(flagtree, hf_ns_activity_natpcb_zombie, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(flagtree, hf_ns_activity_lbstats_sync, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(flagtree, hf_ns_activity_stats_req, tvb, flagoffset, 4, ENC_LITTLE_ENDIAN);

	case NSPR_HEADER_VERSION205:

		if(src_vmname_len){
			proto_tree_add_item(ns_tree,hf_ns_src_vm,tvb,pnstr->data_offset,src_vmname_len,ENC_LITTLE_ENDIAN);
			}

		if(dst_vmname_len){
			proto_tree_add_item(ns_tree,hf_ns_dst_vm,tvb,pnstr->data_offset+src_vmname_len,dst_vmname_len,ENC_LITTLE_ENDIAN);
			}


	case NSPR_HEADER_VERSION204:

		flagoffset = pnstr->clflags_offset;
		flagval = tvb_get_guint8(tvb, flagoffset);

		for (i = 0; i < 5; i++) {
			bpos = 1 << i;
			if (flagval & bpos) {
				if (first_flag) {
					wmem_strbuf_truncate(flags_strbuf, 0);
				}
				wmem_strbuf_append_printf(flags_strbuf, "%s%s", first_flag ? "" : ", ", flags[i]);
				first_flag = FALSE;
			}
		}

		proto_tree_add_item(ns_tree, hf_ns_snode, tvb, pnstr->srcnodeid_offset, 2, ENC_LITTLE_ENDIAN);
		proto_tree_add_item(ns_tree, hf_ns_dnode, tvb, pnstr->destnodeid_offset, 2, ENC_LITTLE_ENDIAN);

		flagitem = proto_tree_add_uint_format_value(ns_tree, hf_ns_clflags, tvb, flagoffset, 1, flagval,
						"0x%02x (%s)", flagval, wmem_strbuf_get_str(flags_strbuf));
		flagtree = proto_item_add_subtree(flagitem, ett_ns_flags);

		proto_tree_add_boolean(flagtree, hf_ns_clflags_res, tvb, flagoffset, 1, flagval);
		proto_tree_add_boolean(flagtree, hf_ns_clflags_rssh, tvb, flagoffset, 1, flagval);
		proto_tree_add_boolean(flagtree, hf_ns_clflags_rss, tvb, flagoffset, 1, flagval);
		proto_tree_add_boolean(flagtree, hf_ns_clflags_dfd, tvb, flagoffset, 1, flagval);
		proto_tree_add_boolean(flagtree, hf_ns_clflags_fr, tvb, flagoffset, 1, flagval);
		proto_tree_add_boolean(flagtree, hf_ns_clflags_fp, tvb, flagoffset, 1, flagval);

	case NSPR_HEADER_VERSION203:
		proto_tree_add_item(ns_tree, hf_ns_coreid, tvb, pnstr->coreid_offset, 2, ENC_LITTLE_ENDIAN);
		/* fall through to next case */

	case NSPR_HEADER_VERSION202:
		col_add_fstr(pinfo->cinfo, COL_8021Q_VLAN_ID, "%d", tvb_get_letohs(tvb, pnstr->vlantag_offset));
		proto_tree_add_item(ns_tree, hf_ns_vlantag, tvb, pnstr->vlantag_offset, 2, ENC_LITTLE_ENDIAN);
		/* fall through to next case */

	case NSPR_HEADER_VERSION201:
		proto_tree_add_item(ns_tree, hf_ns_pcbdevno, tvb, pnstr->pcb_offset, 4, ENC_LITTLE_ENDIAN);
		ti = proto_tree_add_item(ns_tree, hf_ns_devno, tvb, pnstr->pcb_offset, 4, ENC_LITTLE_ENDIAN);
		PROTO_ITEM_SET_HIDDEN(ti);

		proto_tree_add_item(ns_tree, hf_ns_l_pcbdevno, tvb, pnstr->l_pcb_offset, 4, ENC_LITTLE_ENDIAN);
		ti = proto_tree_add_item(ns_tree, hf_ns_devno, tvb, pnstr->l_pcb_offset, 4, ENC_LITTLE_ENDIAN);
		PROTO_ITEM_SET_HIDDEN(ti);

		break;

	default:
		break;
	}

	/* Dissect as Ethernet */
	offset = pnstr->eth_offset;
	next_tvb_eth_client = tvb_new_subset_remaining(tvb, offset);
	call_dissector(eth_withoutfcs_handle, next_tvb_eth_client, pinfo, tree);
}
Beispiel #5
0
static void
dissect_irc_response(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, int offset, int linelen)
{
    proto_tree *response_tree, *command_tree = NULL;
    proto_item *response_item, *command_item, *hidden_item;
    int         start_offset                 = offset;
    int         end_offset                   = start_offset+linelen;
    gint        eop_offset                   = -1,
                eoc_offset                   = -1,
                eocp_offset,
                tag_start_offset, tag_end_offset;
    guint8*     str_command;
    guint16     num_command;
    guchar      found_needle                 = 0,
                found_tag_needle             = 0;
    gboolean    first_command_param          = TRUE;

    response_item = proto_tree_add_item(tree, hf_irc_response, tvb, offset, linelen, ENC_ASCII|ENC_NA);
    if (linelen <= 0)
        return;

    response_tree = proto_item_add_subtree(response_item, ett_irc_response );

    /* Check if message has a prefix */
    if (tvb_get_guint8(tvb, offset) == ':')
    {
        /* find the end of the prefix */
        eop_offset = tvb_pbrk_guint8(tvb, offset+1, linelen-1, " ", &found_needle);
        if (eop_offset == -1)
        {
            expert_add_info_format(pinfo, response_item, PI_MALFORMED, PI_ERROR, "Prefix missing ending <space>");
            return;
        }

        proto_tree_add_item(response_tree, hf_irc_response_prefix, tvb, offset+1, eop_offset-offset-1, ENC_ASCII|ENC_NA);
        found_needle = 0;
        offset = eop_offset+1;
    }

    /* clear out any whitespace before command */
    while(offset < end_offset && tvb_get_guint8(tvb, offset) == ' ')
    {
        offset++;
    }
    if (offset == end_offset)
    {
        expert_add_info_format(pinfo, response_item, PI_MALFORMED, PI_ERROR, "Response has no command");
        return;
    }

    eoc_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, " ", &found_needle);
    if (eoc_offset == -1)
    {
        proto_tree_add_item(response_tree, hf_irc_response_command, tvb, offset, end_offset-offset, ENC_ASCII|ENC_NA);
        col_append_fstr( pinfo->cinfo, COL_INFO, " (%s)", tvb_get_ephemeral_string(tvb, offset, end_offset-offset));

        /* if response command is numeric, allow it to be filtered as an integer */
        if ((end_offset-offset == 3) &&
            (isdigit(tvb_get_guint8(tvb, offset))) &&
            (isdigit(tvb_get_guint8(tvb, offset+1))) &&
            (isdigit(tvb_get_guint8(tvb, offset+2))))
        {
            num_command = ((tvb_get_guint8(tvb, offset)-0x30)*100) + ((tvb_get_guint8(tvb, offset+1)-0x30)*10) + (tvb_get_guint8(tvb, offset+2)-0x30);
            hidden_item = proto_tree_add_uint(response_tree, hf_irc_response_num_command, tvb, offset, end_offset-offset, num_command);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
        }
        return;
    }

    proto_tree_add_item(response_tree, hf_irc_response_command, tvb, offset, eoc_offset-offset, ENC_ASCII|ENC_NA);
    str_command = tvb_get_ephemeral_string(tvb, offset, eoc_offset-offset);
    col_append_fstr( pinfo->cinfo, COL_INFO, " (%s)", str_command);

    /* if response command is numeric, allow it to be filtered as an integer */
    if ((eoc_offset-offset == 3) &&
       (isdigit(tvb_get_guint8(tvb, offset))) &&
       (isdigit(tvb_get_guint8(tvb, offset+1))) &&
       (isdigit(tvb_get_guint8(tvb, offset+2))))
    {
        num_command = ((tvb_get_guint8(tvb, offset)-0x30)*100) + ((tvb_get_guint8(tvb, offset+1)-0x30)*10) + (tvb_get_guint8(tvb, offset+2)-0x30);
        hidden_item = proto_tree_add_uint(response_tree, hf_irc_response_num_command, tvb, offset, eoc_offset-offset, num_command);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
    }

    found_needle = 0;
    offset = eoc_offset+1;

    /* clear out any whitespace before command parameter */
    while(offset < end_offset && tvb_get_guint8(tvb, offset) == ' ')
    {
        offset++;
    }
    if (offset == end_offset)
    {
        /* No command parameters */
        return;
    }

    /* Check if message has a trailer */
    if (tvb_get_guint8(tvb, offset) == ':')
    {
        proto_tree_add_item(response_tree, hf_irc_response_trailer, tvb, offset+1, end_offset-offset-1, ENC_ASCII|ENC_NA);
        dissect_irc_tag_data(response_tree, response_item, tvb, offset+1, end_offset-offset-1, pinfo, str_command);
        return;
    }

    while(offset < end_offset)
    {
        eocp_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, " ", &found_needle);
        tag_start_offset = tvb_pbrk_guint8(tvb, offset, end_offset-offset, TAG_DELIMITER, &found_tag_needle);

        /* Create subtree when the first parameter is found */
        if (first_command_param)
        {
            command_item = proto_tree_add_text(response_tree, tvb, offset, end_offset-offset, "Command parameters");
            command_tree = proto_item_add_subtree(command_item, ett_irc_response_command );
            first_command_param = FALSE;
        }

        if ((tag_start_offset == -1) || (eocp_offset < tag_start_offset))
        {
            /* regular message should be dissected */

            found_needle = 0;
            if (eocp_offset == -1)
            {
                proto_tree_add_item(command_tree, hf_irc_response_command_param, tvb, offset, end_offset-offset, ENC_ASCII|ENC_NA);
                return;
            }

            proto_tree_add_item(command_tree, hf_irc_response_command_param, tvb, offset, eocp_offset-offset, ENC_ASCII|ENC_NA);
            offset = eocp_offset+1;

            /* clear out any whitespace before next command parameter */
            while(offset < end_offset && tvb_get_guint8(tvb, offset) == ' ')
            {
                offset++;
            }
            if (offset == end_offset)
            {
                break;
            }

            /* Check if message has a trailer */
            if (tvb_get_guint8(tvb, offset) == ':')
            {
                proto_tree_add_item(response_tree, hf_irc_response_trailer, tvb, offset+1, end_offset-offset-1, ENC_ASCII|ENC_NA);
                dissect_irc_tag_data(response_tree, response_item, tvb, offset+1, end_offset-offset-1, pinfo, str_command);
                return;
            }
        }
        else if ((eocp_offset == -1) || (eocp_offset > tag_start_offset))
        {
            /* tag data dissected */

            found_tag_needle = 0;
            tag_end_offset = tvb_pbrk_guint8(tvb, tag_start_offset+1, end_offset-tag_start_offset-1, TAG_DELIMITER, &found_tag_needle);
            if (tag_end_offset == -1)
            {
                expert_add_info_format(pinfo, response_item, PI_MALFORMED, PI_ERROR, "Missing ending tag delimited (0x01)");
                return;
            }

            dissect_irc_tag_data(response_tree, response_item, tvb, tag_start_offset, tag_end_offset-tag_start_offset, pinfo, str_command);
            offset = tag_end_offset+1;
        }
    }
}
Beispiel #6
0
static void
dissect_smtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  struct smtp_proto_data    *spd_frame_data;
  proto_tree                *smtp_tree = NULL;
  proto_tree                *cmdresp_tree;
  proto_item                *ti, *hidden_item;
  int                       offset = 0;
  int                       request = 0;
  conversation_t            *conversation;
  struct smtp_session_state *session_state;
  const guchar              *line, *linep, *lineend;
  guchar                    c;
  guint32                   code;
  int                       linelen = 0;
  gint                      length_remaining;
  gboolean                  eom_seen = FALSE;
  gint                      next_offset;
  gint                      loffset = 0;
  gboolean                  is_continuation_line;
  int                       cmdlen;
  fragment_data             *frag_msg = NULL;
  tvbuff_t                  *next_tvb;

  /* As there is no guarantee that we will only see frames in the
   * the SMTP conversation once, and that we will see them in
   * order - in Wireshark, the user could randomly click on frames
   * in the conversation in any order in which they choose - we
   * have to store information with each frame indicating whether
   * it contains commands or data or an EOM indication.
   *
   * XXX - what about frames that contain *both*?  TCP is a
   * byte-stream protocol, and there are no guarantees that
   * TCP segment boundaries will correspond to SMTP commands
   * or EOM indications.
   *
   * We only need that for the client->server stream; responses
   * are easy to manage.
   *
   * If we have per frame data, use that, else, we must be on the first
   * pass, so we figure it out on the first pass.
   */

  /*
   * Find or create the conversation for this.
   */
  conversation = find_or_create_conversation(pinfo);

  /*
   * Is there a request structure attached to this conversation?
   */
  session_state = conversation_get_proto_data(conversation, proto_smtp);
  if (!session_state) {
    /*
     * No - create one and attach it.
     */
    session_state = se_alloc(sizeof(struct smtp_session_state));
    session_state->smtp_state = SMTP_STATE_READING_CMDS;
    session_state->crlf_seen = FALSE;
    session_state->data_seen = FALSE;
    session_state->msg_read_len = 0;
    session_state->msg_tot_len = 0;
    session_state->msg_last = TRUE;
    session_state->last_nontls_frame = 0;

    conversation_add_proto_data(conversation, proto_smtp, session_state);
  }

  /* Are we doing TLS?
   * FIXME In my understanding of RFC 2487 client and server can send SMTP cmds
   * after a rejected TLS negotiation
   */
  if (session_state->last_nontls_frame != 0 && pinfo->fd->num > session_state->last_nontls_frame) {
    guint16 save_can_desegment;
    guint32 save_last_nontls_frame;

    /* This is TLS, not raw SMTP. TLS can desegment */
    save_can_desegment = pinfo->can_desegment;
    pinfo->can_desegment = pinfo->saved_can_desegment;

    /* Make sure the SSL dissector will not be called again after decryption */
    save_last_nontls_frame = session_state->last_nontls_frame;
    session_state->last_nontls_frame = 0;

    call_dissector(ssl_handle, tvb, pinfo, tree);

    pinfo->can_desegment = save_can_desegment;
    session_state->last_nontls_frame = save_last_nontls_frame;
    return;
  }

  /* Is this a request or a response? */
  request = pinfo->destport == pinfo->match_uint;

  /*
   * Is there any data attached to this frame?
   */
  spd_frame_data = p_get_proto_data(pinfo->fd, proto_smtp);

  if (!spd_frame_data) {

    /*
     * No frame data.
     */
    if(request) {

      /*
       * Create a frame data structure and attach it to the packet.
       */
      spd_frame_data = se_alloc0(sizeof(struct smtp_proto_data));

      spd_frame_data->conversation_id = conversation->index;
      spd_frame_data->more_frags = TRUE;

      p_add_proto_data(pinfo->fd, proto_smtp, spd_frame_data);

    }

    /*
     * Get the first line from the buffer.
     *
     * Note that "tvb_find_line_end()" will, if it doesn't return
     * -1, return a value that is not longer than what's in the buffer,
     * and "tvb_find_line_end()" will always return a value that is not
     * longer than what's in the buffer, so the "tvb_get_ptr()" call
     * won't throw an exception.
     */
    loffset = offset;
    while (tvb_offset_exists(tvb, loffset)) {
      linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset,
                                  smtp_desegment && pinfo->can_desegment);
      if (linelen == -1) {
        if (offset == loffset) {
          /*
           * We didn't find a line ending, and we're doing desegmentation;
           * tell the TCP dissector where the data for this message starts
           * in the data it handed us, and tell it we need more bytes
           */
          pinfo->desegment_offset = loffset;
          pinfo->desegment_len = DESEGMENT_ONE_MORE_SEGMENT;
          return;
        } else {
          linelen = tvb_length_remaining(tvb, loffset);
          next_offset = loffset + linelen;
        }
      }
      line = tvb_get_ptr(tvb, loffset, linelen);

      /*
       * Check whether or not this packet is an end of message packet
       * We should look for CRLF.CRLF and they may be split.
       * We have to keep in mind that we may see what we want on
       * two passes through here ...
       */
      if (session_state->smtp_state == SMTP_STATE_READING_DATA) {
        /*
         * The order of these is important ... We want to avoid
         * cases where there is a CRLF at the end of a packet and a
         * .CRLF at the begining of the same packet.
         */
        if ((session_state->crlf_seen && tvb_strneql(tvb, loffset, ".\r\n", 3) == 0) ||
            tvb_strneql(tvb, loffset, "\r\n.\r\n", 5) == 0)
          eom_seen = TRUE;

        length_remaining = tvb_length_remaining(tvb, loffset);
        if (length_remaining == tvb_reported_length_remaining(tvb, loffset) &&
            tvb_strneql(tvb, loffset + length_remaining - 2, "\r\n", 2) == 0)
          session_state->crlf_seen = TRUE;
        else
          session_state->crlf_seen = FALSE;
      }

      /*
       * OK, Check if we have seen a DATA request. We do it here for
       * simplicity, but we have to be careful below.
       */
      if (request) {
        if (session_state->smtp_state == SMTP_STATE_READING_DATA) {
          /*
           * This is message data.
           */
          if (eom_seen) { /* Seen the EOM */
            /*
             * EOM.
             * Everything that comes after it is commands.
             */
            spd_frame_data->pdu_type = SMTP_PDU_EOM;
            session_state->smtp_state = SMTP_STATE_READING_CMDS;
            break;
          } else {
            /*
             * Message data with no EOM.
             */
            spd_frame_data->pdu_type = SMTP_PDU_MESSAGE;

            if (session_state->msg_tot_len > 0) {
              /*
               * We are handling a BDAT message.
               * Check if we have reached end of the data chunk.
               */
              session_state->msg_read_len += tvb_length_remaining(tvb, loffset);

              if (session_state->msg_read_len == session_state->msg_tot_len) {
                /*
                 * We have reached end of BDAT data chunk.
                 * Everything that comes after this is commands.
                 */
                session_state->smtp_state = SMTP_STATE_READING_CMDS;

                if (session_state->msg_last) {
                  /*
                   * We have found the LAST data chunk.
                   * The message can now be reassembled.
                   */
                  spd_frame_data->more_frags = FALSE;
                }

                break; /* no need to go through the remaining lines */
              }
            }
          }
        } else {
          /*
           * This is commands - unless the capture started in the
           * middle of a session, and we're in the middle of data.
           *
           * Commands are not necessarily 4 characters; look
           * for a space or the end of the line to see where
           * the putative command ends.
           */
          linep = line;
          lineend = line + linelen;
          while (linep < lineend && (c = *linep) != ' ')
            linep++;
          cmdlen = (int)(linep - line);
          if (line_is_smtp_command(line, cmdlen)) {
            if (g_ascii_strncasecmp(line, "DATA", 4) == 0) {
              /*
               * DATA command.
               * This is a command, but everything that comes after it,
               * until an EOM, is data.
               */
              spd_frame_data->pdu_type = SMTP_PDU_CMD;
              session_state->smtp_state = SMTP_STATE_READING_DATA;
              session_state->data_seen = TRUE;
            } else if (g_ascii_strncasecmp(line, "BDAT", 4) == 0) {
              /*
               * BDAT command.
               * This is a command, but everything that comes after it,
               * until given length is received, is data.
               */
              guint32 msg_len;

              msg_len = strtoul (line+5, NULL, 10);

              spd_frame_data->pdu_type = SMTP_PDU_CMD;
              session_state->data_seen = TRUE;
              session_state->msg_tot_len += msg_len;

              if (msg_len == 0) {
                /* No data to read, next will be a command */
                session_state->smtp_state = SMTP_STATE_READING_CMDS;
              } else {
                session_state->smtp_state = SMTP_STATE_READING_DATA;
              }

              if (g_ascii_strncasecmp(line+linelen-4, "LAST", 4) == 0) {
                /*
                 * This is the last data chunk.
                 */
                session_state->msg_last = TRUE;

                if (msg_len == 0) {
                  /*
                   * No more data to expect.
                   * The message can now be reassembled.
                   */
                  spd_frame_data->more_frags = FALSE;
                }
              } else {
                session_state->msg_last = FALSE;
              }
            } else if (g_ascii_strncasecmp(line, "STARTTLS", 8) == 0) {
              /*
               * STARTTLS command.
               * This is a command, but if the response is 220,
               * everything after the response is TLS.
               */
              session_state->smtp_state = SMTP_STATE_AWAITING_STARTTLS_RESPONSE;
              spd_frame_data->pdu_type = SMTP_PDU_CMD;
            } else {
              /*
               * Regular command.
               */
              spd_frame_data->pdu_type = SMTP_PDU_CMD;
            }
          } else {
            /*
             * Assume it's message data.
             */
            spd_frame_data->pdu_type = session_state->data_seen ? SMTP_PDU_MESSAGE : SMTP_PDU_CMD;
          }
        }
      }

      /*
       * Step past this line.
       */
      loffset = next_offset;
    }
  }


  /*
   * From here, we simply add items to the tree and info to the info
   * fields ...
   */

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

  if (check_col(pinfo->cinfo, COL_INFO)) {  /* Add the appropriate type here */
    col_clear(pinfo->cinfo, COL_INFO);

    /*
     * If it is a request, we have to look things up, otherwise, just
     * display the right things
     */

    if (request) {
      /* We must have frame_data here ... */
      switch (spd_frame_data->pdu_type) {
      case SMTP_PDU_MESSAGE:

        length_remaining = tvb_length_remaining(tvb, offset);
        col_set_str(pinfo->cinfo, COL_INFO, smtp_data_desegment ? "C: DATA fragment" : "C: Message Body");
        col_append_fstr(pinfo->cinfo, COL_INFO, ", %d byte%s", length_remaining,
                        plurality (length_remaining, "", "s"));
        break;

      case SMTP_PDU_EOM:
        col_set_str(pinfo->cinfo, COL_INFO, "C: .");
        break;

      case SMTP_PDU_CMD:
        loffset = offset;
        while (tvb_offset_exists(tvb, loffset)) {
          /*
           * Find the end of the line.
           */
          linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);
          line = tvb_get_ptr(tvb, loffset, linelen);

          if(loffset == offset)
            col_append_fstr(pinfo->cinfo, COL_INFO, "C: %s",
                            format_text(line, linelen));
          else {
            col_append_fstr(pinfo->cinfo, COL_INFO, " | %s",
                            format_text(line, linelen));
          }

          loffset = next_offset;
        }
        break;
      }
    } else {
      loffset = offset;
      while (tvb_offset_exists(tvb, loffset)) {
        /*
         * Find the end of the line.
         */
        linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);
        line = tvb_get_ptr(tvb, loffset, linelen);

        if (loffset == offset)
          col_append_fstr(pinfo->cinfo, COL_INFO, "S: %s",
                          format_text(line, linelen));
        else {
          col_append_fstr(pinfo->cinfo, COL_INFO, " | %s",
                          format_text(line, linelen));
        }

        loffset = next_offset;
      }
    }
  }

  if (tree) { /* Build the tree info ... */
    ti = proto_tree_add_item(tree, proto_smtp, tvb, offset, -1, FALSE);
    smtp_tree = proto_item_add_subtree(ti, ett_smtp);
  }

  if (request) {
    /*
     * Check out whether or not we can see a command in there ...
     * What we are looking for is not data_seen and the word DATA
     * and not eom_seen.
     *
     * We will see DATA and session_state->data_seen when we process the
     * tree view after we have seen a DATA packet when processing
     * the packet list pane.
     *
     * On the first pass, we will not have any info on the packets
     * On second and subsequent passes, we will.
     */
    switch (spd_frame_data->pdu_type) {

    case SMTP_PDU_MESSAGE:
      if (smtp_data_desegment) {
        frag_msg = fragment_add_seq_next(tvb, 0, pinfo, spd_frame_data->conversation_id,
                                         smtp_data_segment_table, smtp_data_reassembled_table,
                                         tvb_length(tvb), spd_frame_data->more_frags);
      } else {
        /*
         * Message body.
         * Put its lines into the protocol tree, a line at a time.
         */
        dissect_smtp_data(tvb, offset, smtp_tree);
      }
      break;

    case SMTP_PDU_EOM:
      /*
       * End-of-message-body indicator.
       *
       * XXX - what about stuff after the first line?
       * Unlikely, as the client should wait for a response to the
       * DATA command this terminates before sending another
       * request, but we should probably handle it.
       */
      proto_tree_add_text(smtp_tree, tvb, offset, linelen, "C: .");

      if (smtp_data_desegment) {
        /* add final data segment */
        if (loffset)
          fragment_add_seq_next(tvb, 0, pinfo, spd_frame_data->conversation_id,
                                smtp_data_segment_table, smtp_data_reassembled_table,
                                loffset, spd_frame_data->more_frags);

        /* terminate the desegmentation */
        frag_msg = fragment_end_seq_next (pinfo, spd_frame_data->conversation_id, smtp_data_segment_table,
                                          smtp_data_reassembled_table);
      }
      break;

    case SMTP_PDU_CMD:
      /*
       * Command.
       *
       * XXX - what about stuff after the first line?
       * Unlikely, as the client should wait for a response to the
       * previous command before sending another request, but we
       * should probably handle it.
       */

      loffset = offset;
      while (tvb_offset_exists(tvb, loffset)) {
        /*
         * Find the end of the line.
         */
        linelen = tvb_find_line_end(tvb, loffset, -1, &next_offset, FALSE);

        if (linelen >= 4)
          cmdlen = 4;
        else
          cmdlen = linelen;
        hidden_item = proto_tree_add_boolean(smtp_tree, hf_smtp_req, tvb,
                                             0, 0, TRUE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);

        /*
         * Put the command line into the protocol tree.
         */
        ti = proto_tree_add_text(smtp_tree, tvb, loffset, next_offset - loffset,
                                 "Command: %s",
                                 tvb_format_text(tvb, loffset, next_offset - loffset));
        cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp);

        proto_tree_add_item(cmdresp_tree, hf_smtp_req_command, tvb,
                            loffset, cmdlen, FALSE);
        if (linelen > 5) {
          proto_tree_add_item(cmdresp_tree, hf_smtp_req_parameter, tvb,
                              loffset + 5, linelen - 5, FALSE);
        }

        if (smtp_data_desegment && !spd_frame_data->more_frags) {
          /* terminate the desegmentation */
          frag_msg = fragment_end_seq_next (pinfo, spd_frame_data->conversation_id, smtp_data_segment_table,
                                            smtp_data_reassembled_table);
        }

        /*
         * Step past this line.
         */
        loffset = next_offset;
      }
    }

    if (smtp_data_desegment) {
      next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled DATA",
                                          frag_msg, &smtp_data_frag_items, NULL, smtp_tree);
      if (next_tvb) {
        /* XXX: this is presumptious - we may have negotiated something else */
        if (imf_handle) {
          call_dissector(imf_handle, next_tvb, pinfo, tree);
        } else {
          /*
           * Message body.
           * Put its lines into the protocol tree, a line at a time.
           */
          dissect_smtp_data(tvb, offset, smtp_tree);
        }

        pinfo->fragmented = FALSE;
      } else {
        pinfo->fragmented = TRUE;
      }
    }
  } else {
    /*
     * Process the response, a line at a time, until we hit a line
     * that doesn't have a continuation indication on it.
     */
    if (tree) {
      hidden_item = proto_tree_add_boolean(smtp_tree, hf_smtp_rsp, tvb,
                                           0, 0, TRUE);
      PROTO_ITEM_SET_HIDDEN(hidden_item);
    }

    while (tvb_offset_exists(tvb, offset)) {
      /*
       * Find the end of the line.
       */
      linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);

      if (tree) {
        /*
         * Put it into the protocol tree.
         */
        ti = proto_tree_add_text(smtp_tree, tvb, offset,
                                 next_offset - offset, "Response: %s",
                                 tvb_format_text(tvb, offset,
                                                 next_offset - offset));
        cmdresp_tree = proto_item_add_subtree(ti, ett_smtp_cmdresp);
      } else
        cmdresp_tree = NULL;

      /*
       * Is it a continuation line?
       */
      is_continuation_line =
        (linelen >= 4 && tvb_get_guint8(tvb, offset + 3) == '-');

      line = tvb_get_ptr(tvb, offset, linelen);
      if (linelen >= 3 && isdigit(line[0]) && isdigit(line[1])
          && isdigit(line[2])) {
        /*
         * We have a 3-digit response code.
         */
        code = (line[0] - '0')*100 + (line[1] - '0')*10 + (line[2] - '0');

        /*
         * If we're awaiting the response to a STARTTLS code, this
         * is it - if it's 220, all subsequent traffic will
         * be TLS, otherwise we're back to boring old SMTP.
         */
        if (session_state->smtp_state == SMTP_STATE_AWAITING_STARTTLS_RESPONSE) {
          if (code == 220) {
            /* This is the last non-TLS frame. */
            session_state->last_nontls_frame = pinfo->fd->num;
          }
          session_state->smtp_state =  SMTP_STATE_READING_CMDS;
        }

        if (tree) {
          /*
           * Put the response code and parameters into the protocol tree.
           */
          proto_tree_add_uint(cmdresp_tree, hf_smtp_rsp_code, tvb, offset, 3,
                              code);

          if (linelen >= 4) {
            proto_tree_add_item(cmdresp_tree, hf_smtp_rsp_parameter, tvb,
                                offset + 4, linelen - 4, FALSE);
          }
        }
      }

      /*
       * Step past this line.
       */
      offset = next_offset;

      /*
       * If it's not a continuation line, quit.
       */
      /* if (!is_continuation_line)
         break; */
    }
  }
}
static void
dissect_tacplus(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	tvbuff_t	*new_tvb=NULL;
	proto_tree      *tacplus_tree;
	proto_item      *ti, *hidden_item;
	guint8		version,flags;
	proto_tree      *flags_tree;
	proto_item      *tf;
	proto_item	*tmp_pi;
	guint32		len;
	gboolean	request=( pinfo->destport == TCP_PORT_TACACS );
	const char	*key=NULL;

	len = tvb_get_ntohl(tvb, 8);

	if(len > (guint)tvb_length_remaining(tvb, 12) &&
	   pinfo->can_desegment && tacplus_preference_desegment) {
		pinfo->desegment_offset = 0;
		pinfo->desegment_len = len;
		return;
	}

	if( request ) {
		key=find_key( &pinfo->dst, &pinfo->src );
	} else {
		key=find_key(  &pinfo->src, &pinfo->dst );
	}
	col_set_str(pinfo->cinfo, COL_PROTOCOL, "TACACS+");

	col_add_fstr( pinfo->cinfo, COL_INFO, "%s: %s",
				request ? "Q" : "R",
				val_to_str(tvb_get_guint8(tvb,1), tacplus_type_vals, "Unknown (0x%02x)"));

	if (tree)
	{
		ti = proto_tree_add_item(tree, proto_tacplus, tvb, 0, -1, ENC_NA);

		tacplus_tree = proto_item_add_subtree(ti, ett_tacplus);
		if (pinfo->match_uint == pinfo->destport)
		{
			hidden_item = proto_tree_add_boolean(tacplus_tree,
			    hf_tacplus_request, tvb, 0, 0, TRUE);
		}
		else
		{
			hidden_item = proto_tree_add_boolean(tacplus_tree,
			    hf_tacplus_response, tvb, 0, 0, TRUE);
		}
		PROTO_ITEM_SET_HIDDEN(hidden_item);

		version = tvb_get_guint8(tvb,0);
		proto_tree_add_uint_format_value(tacplus_tree, hf_tacplus_majvers, tvb, 0, 1,
		    version,
		    "%s",
		    (version&0xf0)==0xc0?"TACACS+":"Unknown Version");
		proto_tree_add_uint(tacplus_tree, hf_tacplus_minvers, tvb, 0, 1,
		    version&0xf);
		proto_tree_add_item(tacplus_tree, hf_tacplus_type, tvb, 1, 1,
		    ENC_BIG_ENDIAN);
		proto_tree_add_item(tacplus_tree, hf_tacplus_seqno, tvb, 2, 1,
		    ENC_BIG_ENDIAN);
		flags = tvb_get_guint8(tvb,3);
		tf = proto_tree_add_uint_format_value(tacplus_tree, hf_tacplus_flags,
		    tvb, 3, 1, flags,
		    "0x%02x (%s payload, %s)", flags,
		    (flags&FLAGS_UNENCRYPTED) ? "Unencrypted" : "Encrypted",
		    (flags&FLAGS_SINGLE) ? "Single connection" : "Multiple Connections" );
		flags_tree = proto_item_add_subtree(tf, ett_tacplus_flags);
		proto_tree_add_boolean(flags_tree, hf_tacplus_flags_payload_type,
		    tvb, 3, 1, flags);
		proto_tree_add_boolean(flags_tree, hf_tacplus_flags_connection_type,
		    tvb, 3, 1, flags);
		proto_tree_add_item(tacplus_tree, hf_tacplus_session_id, tvb, 4, 4,
		    ENC_BIG_ENDIAN);

		tmp_pi = proto_tree_add_uint(tacplus_tree, hf_tacplus_packet_len, tvb, 8, 4, len);
		if ((gint)len < 1) {
			expert_add_info_format(pinfo, tmp_pi, &ei_tacplus_packet_len_invalid, "Invalid length: %u", len);
		}

		tmp_pi = proto_tree_add_text(tacplus_tree, tvb, TAC_PLUS_HDR_SIZE, len, "%s%s",
					((flags&FLAGS_UNENCRYPTED)?"":"Encrypted "), request?"Request":"Reply" );

		if( flags&FLAGS_UNENCRYPTED ) {
			new_tvb = tvb_new_subset( tvb, TAC_PLUS_HDR_SIZE, len, len );
		}  else {
			new_tvb=NULL;
			if( key && *key ){
				tacplus_decrypted_tvb_setup( tvb, &new_tvb, pinfo, len, version, key );
			}
		}
		if( new_tvb ) {
			/* Check to see if I've a decrypted tacacs packet */
			if( !(flags&FLAGS_UNENCRYPTED) ){
				tmp_pi = proto_tree_add_text(tacplus_tree, new_tvb, 0, len, "Decrypted %s",
							request?"Request":"Reply" );
			}
			dissect_tacplus_body( tvb, new_tvb, proto_item_add_subtree( tmp_pi, ett_tacplus_body ));
		}
	}
}
Beispiel #8
0
static void
dissect_ftp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    gboolean        is_request;
    proto_tree     *ftp_tree          = NULL;
    proto_tree     *reqresp_tree      = NULL;
    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_text(ftp_tree, tvb, 0, next_offset, "%s",
            tvb_format_text(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 && isdigit(line[0]) && isdigit(line[1])
            && 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_format(pinfo, item, PI_MALFORMED, PI_WARN,
                    "EPRT arguments must have the form: |<family>|<addr>|<port>|");
        }
    }

    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,
                            (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_format(pinfo, item, PI_MALFORMED, PI_WARN,
                        "EPSV arguments must have the form (|||<port>|)");
            }
        }
    }

    /*
     * 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_text(ftp_tree, tvb, offset,
                next_offset - offset, "%s",
                tvb_format_text(tvb, offset, next_offset - offset));
        offset = next_offset;
    }
}
static void
display_socks_v4(tvbuff_t *tvb, int offset, packet_info *pinfo,
	proto_tree *tree, socks_hash_entry_t *hash_info) {


/* Display the protocol tree for the V4 version. This routine uses the	*/
/* stored conversation information to decide what to do with the row.	*/
/* Per packet information would have been better to do this, but we	*/
/* didn't have that when I wrote this. And I didn't expect this to get	*/
/* so messy.								*/


	proto_item *hidden_item;
	guint command;
	unsigned char ipaddr[4];
	guint username_len, domainname_len;

					/* Display command from client */
	if (compare_packet( hash_info->connect_row)){

		proto_tree_add_text( tree, tvb, offset, 1,
				"Version: %u", hash_info->version);
		++offset;
		command = tvb_get_guint8(tvb, offset);

		proto_tree_add_text( tree, tvb, offset, 1,
			"Command: %u (%s)", command,
				get_command_name( command));
		++offset;

						/* Do remote port	*/
		proto_tree_add_item( tree, hf_socks_dstport, tvb, offset, 2,
				FALSE);
		offset += 2;

						/* Do destination address */
		tvb_memcpy(tvb, ipaddr, offset, 4);
		proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset,
				4, FALSE);

		offset += 4;

/*XXX check this, needs to do length checking	 */
/* Should perhaps do TCP reassembly as well */
		if ( tvb_offset_exists(tvb, offset)) {
						/* display user name 	*/
			username_len = tvb_strsize(tvb, offset);
			proto_tree_add_item( tree, hf_user_name, tvb, offset,
				username_len, FALSE);
			offset += username_len;
			if ( ipaddr[0] == 0 && ipaddr[1] == 0 &&
			     ipaddr[2] == 0 && ipaddr[3] != 0) {
			     	/* 0.0.0.x , where x!=0 means v4a support */
			     	domainname_len = tvb_strsize(tvb, offset);
				proto_tree_add_item( tree, hf_v4a_dns_name,
					tvb, offset, domainname_len,
					FALSE);
			}
		}

	}
				/*Display command response from server*/

	else if ( compare_packet( hash_info->cmd_reply_row)){

		proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1,
				FALSE);
		++offset;
						/* Do results code	*/
		proto_tree_add_item( tree, hf_socks_results_4, tvb, offset, 1, FALSE);
		hidden_item = proto_tree_add_item(tree, hf_socks_results, tvb, offset, 1, FALSE);
		PROTO_ITEM_SET_HIDDEN(hidden_item);

		++offset;

						/* Do remote port	*/
		proto_tree_add_item( tree, hf_socks_dstport, tvb, offset, 2,
				FALSE);
		offset += 2;
						/* Do remote address	*/
		proto_tree_add_item( tree, hf_socks_ip_dst, tvb, offset, 4,
			FALSE);
	}

	else if ( compare_packet( hash_info->v4_user_name_row)){

/*XXX check this, needs to do length checking	 */
/* Should perhaps do TCP reassembly as well */
		if ( tvb_offset_exists(tvb, offset)) {
			proto_tree_add_text( tree, tvb, offset,
				tvb_strsize(tvb, offset),
				"User Name: %s", tvb_get_ptr(tvb, offset, -1));
		}
	}
}
Beispiel #10
0
static void dissect_tns_accept(tvbuff_t *tvb, int offset, packet_info *pinfo,
	proto_tree *tree, proto_tree *tns_tree)
{
	proto_tree *accept_tree = NULL, *ti;
	proto_item *hidden_item;
	int accept_offset;
	int accept_len;
	int tns_offset = offset-8;

	if ( tree )
	{
		ti = proto_tree_add_text(tns_tree, tvb, offset, -1,
		    "Accept");
		accept_tree = proto_item_add_subtree(ti, ett_tns_accept);

		hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_accept, tvb,
				    0, 0, TRUE);
		PROTO_ITEM_SET_HIDDEN(hidden_item);
	}

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

	if ( accept_tree )
	{
		proto_tree_add_item(accept_tree, hf_tns_version, tvb,
			offset, 2, ENC_BIG_ENDIAN);
	}
	offset += 2;

	if ( accept_tree )
	{
		proto_tree *sopt_tree = NULL;

		ti = proto_tree_add_item(accept_tree, hf_tns_service_options,
			tvb, offset, 2, ENC_BIG_ENDIAN);

		sopt_tree = proto_item_add_subtree(ti, ett_tns_sopt_flag);

		dissect_tns_service_options(tvb, offset, sopt_tree);

	}
	offset += 2;

	if ( accept_tree )
	{
		proto_tree_add_item(accept_tree, hf_tns_sdu_size, tvb,
			offset, 2, ENC_BIG_ENDIAN);
	}
	offset += 2;

	if ( accept_tree )
	{
		proto_tree_add_item(accept_tree, hf_tns_max_tdu_size, tvb,
			offset, 2, ENC_BIG_ENDIAN);
	}
	offset += 2;

	if ( accept_tree )
	{
		proto_tree_add_item(accept_tree, hf_tns_value_of_one, tvb,
			offset, 2, ENC_NA);
	}
	offset += 2;

	accept_len = tvb_get_ntohs(tvb, offset);
	if ( accept_tree )
	{
		proto_tree_add_uint(accept_tree, hf_tns_accept_data_length, tvb,
			offset, 2, accept_len);
	}
	offset += 2;

	accept_offset = tvb_get_ntohs(tvb, offset);
	if ( accept_tree )
	{
		proto_tree_add_uint(accept_tree, hf_tns_accept_data_offset, tvb,
			offset, 2, accept_offset);
	}
	offset += 2;

	if ( accept_tree )
	{
		proto_tree *cflag_tree = NULL;

		ti = proto_tree_add_item(accept_tree, hf_tns_connect_flags0, tvb,
			offset, 1, ENC_BIG_ENDIAN);

		cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag);

		dissect_tns_connect_flag(tvb, offset, cflag_tree);

	}
	offset += 1;

	if ( accept_tree )
	{
		proto_tree *cflag_tree = NULL;

		ti = proto_tree_add_item(accept_tree, hf_tns_connect_flags1, tvb,
			offset, 1, ENC_BIG_ENDIAN);

		cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag);

		dissect_tns_connect_flag(tvb, offset, cflag_tree);

	}
	/* offset += 1; */

	if ( accept_tree && accept_len > 0)
	{
		proto_tree_add_item(accept_tree, hf_tns_accept_data, tvb,
			tns_offset+accept_offset, -1, ENC_ASCII|ENC_NA);
	}
	return;
}
int dissect_lua(tvbuff_t* tvb, packet_info* pinfo, proto_tree* tree) {
    int consumed_bytes = tvb->length;
    lua_pinfo = pinfo;
    lua_tvb = tvb;

    lua_tree = g_malloc(sizeof(struct _wslua_treeitem));
    lua_tree->tree = tree;
    lua_tree->item = proto_tree_add_text(tree,tvb,0,0,"lua fake item");
    lua_tree->expired = FALSE;
    PROTO_ITEM_SET_HIDDEN(lua_tree->item);

    /*
     * almost equivalent to Lua:
     * dissectors[current_proto](tvb,pinfo,tree)
     */

    lua_settop(L,0);

    lua_rawgeti(L, LUA_REGISTRYINDEX, lua_dissectors_table_ref);

    lua_pushstring(L, pinfo->current_proto);
    lua_gettable(L, -2);

    lua_remove(L,1);


    if (lua_isfunction(L,1)) {

        push_Tvb(L,tvb);
        push_Pinfo(L,pinfo);
        push_TreeItem(L,lua_tree);

        if  ( lua_pcall(L,3,1,0) ) {
            const gchar* error = lua_tostring(L,-1);

            proto_item* pi = proto_tree_add_text(tree,tvb,0,0,"Lua Error: %s",error);
            expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_ERROR ,"Lua Error");
        } else {

            /* if the Lua dissector reported the consumed bytes, pass it to our caller */
            if (lua_isnumber(L, -1)) { 
                /* we got the consumed bytes or the missing bytes as a negative number */
                consumed_bytes = (int) lua_tonumber(L, -1);
                lua_pop(L, 1);
            }
        }

    } else {
        proto_item* pi = proto_tree_add_text(tree,tvb,0,0,"Lua Error: did not find the %s dissector"
                                             " in the dissectors table",pinfo->current_proto);

        expert_add_info_format(pinfo, pi, PI_UNDECODED, PI_ERROR ,"Lua Error");
    }

    register_frame_end_routine(lua_frame_end);

    lua_pinfo = NULL;
    lua_tree = NULL;
    lua_tvb = NULL;

    return consumed_bytes;

}
static void
dissect_lpd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*lpd_tree;
	proto_item	*ti, *hidden_item;
	enum lpr_type	lpr_packet_type;
	guint8		code;
	gint		printer_len;

	/* This information comes from the LPRng HOWTO, which also describes
		RFC 1179. http://www.astart.com/lprng/LPRng-HOWTO.html */
	static const value_string lpd_client_code[] = {
		{ 1, "LPC: start print / jobcmd: abort" },
		{ 2, "LPR: transfer a printer job / jobcmd: receive control file" },
		{ 3, "LPQ: print short form of queue status / jobcmd: receive data file" },
		{ 4, "LPQ: print long form of queue status" },
		{ 5, "LPRM: remove jobs" },
		{ 6, "LPRng lpc: do control operation" },
		{ 7, "LPRng lpr: transfer a block format print job" },
		{ 8, "LPRng lpc: secure command transfer" },
		{ 9, "LPRng lpq: verbose status information" },
		{ 0, NULL }
	};
	static const value_string lpd_server_code[] = {
		{ 0, "Success: accepted, proceed" },
		{ 1, "Queue not accepting jobs" },
		{ 2, "Queue temporarily full, retry later" },
		{ 3, "Bad job format, do not retry" },
		{ 0, NULL }
	};

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

	/* rfc1179 states that all responses are 1 byte long */
	code = tvb_get_guint8(tvb, 0);
	if (tvb_reported_length(tvb) == 1) {
		lpr_packet_type = response;
	}
	else if (code <= 9) {
		lpr_packet_type = request;
	}
	else {
		lpr_packet_type = unknown;
	}

	if (lpr_packet_type == request && code !=0) {
		col_add_str(pinfo->cinfo, COL_INFO, val_to_str(code, lpd_client_code, "Unknown client code: %u"));
	}
	else if (lpr_packet_type == response) {
		col_set_str(pinfo->cinfo, COL_INFO, "LPD response");
	}
	else {
		col_set_str(pinfo->cinfo, COL_INFO, "LPD continuation");
	}

	if (tree) {
		ti = proto_tree_add_item(tree, proto_lpd, tvb, 0, -1, ENC_NA);
		lpd_tree = proto_item_add_subtree(ti, ett_lpd);

		if (lpr_packet_type == response) {
		  hidden_item = proto_tree_add_boolean(lpd_tree, hf_lpd_response,
		  				tvb, 0, 0, TRUE);
		} else {
		  hidden_item = proto_tree_add_boolean(lpd_tree, hf_lpd_request,
		  				tvb, 0, 0, TRUE);
		}
		PROTO_ITEM_SET_HIDDEN(hidden_item);

		if (lpr_packet_type == request) {
			printer_len = find_printer_string(tvb, 1);

			if (code <= 9 && printer_len != -1) {
				proto_tree_add_text(lpd_tree, tvb, 0, 1, "%s",
					val_to_str(code, lpd_client_code, "Unknown client code: %u"));
				proto_tree_add_text(lpd_tree, tvb, 1, printer_len,
					 "Printer/options: %s",
					 tvb_format_text(tvb, 1, printer_len));
			}
			else {
				call_dissector(data_handle,tvb, pinfo, lpd_tree);
			}
		}
		else if (lpr_packet_type == response) {
			if (code <= 3) {
				proto_tree_add_text(lpd_tree, tvb, 0, 1,
					"Response: %s", val_to_str(code, lpd_server_code, "Unknown server code: %u"));
			}
			else {
				call_dissector(data_handle,tvb, pinfo, lpd_tree);
			}
		}
		else {
			call_dissector(data_handle,tvb, pinfo, lpd_tree);
		}
	}
}
Beispiel #13
0
static int
dissect_websocket_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ws_tree, guint8 opcode, guint64 payload_length, guint8 mask, const guint8* masking_key)
{
  int offset = 0;
  int payload_length_32bit;
  proto_item *ti_unmask, *ti;
  proto_tree *pl_tree, *mask_tree = NULL;
  tvbuff_t  *unmask_tvb    = NULL;

  /* Wireshark does not handle packets larger than 2^31-1 bytes. */
  payload_length_32bit = (int)payload_length;
  if (payload_length != (guint64)payload_length_32bit) {
    proto_tree_add_text(ws_tree, tvb, offset, -1, "Payload length %" G_GINT64_MODIFIER "u is too large to dissect",
                        payload_length);
    return tvb_length(tvb);
  }

  /* Payload */
  ti = proto_tree_add_item(ws_tree, hf_ws_payload, tvb, offset, payload_length_32bit, ENC_NA);
  pl_tree = proto_item_add_subtree(ti, ett_ws_pl);
  if(mask){
    unmask_tvb = tvb_unmasked(tvb, offset, payload_length_32bit, masking_key);
    tvb_set_child_real_data_tvbuff(tvb, unmask_tvb);
    add_new_data_source(pinfo, unmask_tvb, payload_length_32bit > (int) tvb_length(unmask_tvb) ? "Unmasked Data (truncated)" : "Unmasked Data");
    ti = proto_tree_add_item(ws_tree, hf_ws_payload_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA);
    mask_tree = proto_item_add_subtree(ti, ett_ws_mask);
  }

  /* Extension Data */
  /* TODO: Add dissector of Extension (not extension available for the moment...) */

  /* Application Data */
  switch(opcode){

    case WS_CONTINUE: /* Continue */
      proto_tree_add_item(pl_tree, hf_ws_payload_continue, tvb, offset, payload_length_32bit, ENC_NA);
      /* TODO: Add Fragmentation support... */
    break;

    case WS_TEXT: /* Text */
    if(mask){

      proto_tree_add_item(pl_tree, hf_ws_payload_text_mask, tvb, offset, payload_length_32bit, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text_unmask, unmask_tvb, offset, payload_length_32bit,  ENC_UTF_8|ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text, unmask_tvb, offset, payload_length_32bit,  ENC_UTF_8|ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_text, tvb, offset, payload_length_32bit, ENC_UTF_8|ENC_NA);

    }
    offset += payload_length_32bit;
    break;

    case WS_BINARY: /* Binary */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_binary_mask, tvb, offset, payload_length_32bit, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_binary, tvb, offset, payload_length_32bit, ENC_NA);
    }
    offset += payload_length_32bit;
    break;

    case WS_CLOSE: /* Close */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_close_mask, tvb, offset, payload_length_32bit, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_status_code, unmask_tvb, offset, 2, ENC_BIG_ENDIAN);
      PROTO_ITEM_SET_GENERATED(ti_unmask);

      if(payload_length_32bit > 2){
        ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_reason, unmask_tvb, offset+2, payload_length_32bit-2, ENC_ASCII|ENC_NA);
        PROTO_ITEM_SET_GENERATED(ti_unmask);
      }
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_close, tvb, offset, payload_length_32bit, ENC_NA);
      proto_tree_add_item(pl_tree, hf_ws_payload_close_status_code, tvb, offset, 2, ENC_BIG_ENDIAN);
      if(payload_length_32bit > 2){
        proto_tree_add_item(pl_tree, hf_ws_payload_close_reason, tvb, offset+2, payload_length_32bit-2, ENC_ASCII|ENC_NA);
      }
    }
    offset += payload_length_32bit;
    break;

    case WS_PING: /* Ping */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_ping_mask, tvb, offset, payload_length_32bit, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_ping, tvb, offset, payload_length_32bit, ENC_NA);
    }
    offset += payload_length_32bit;
    break;

    case WS_PONG: /* Pong */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_pong_mask, tvb, offset, payload_length_32bit, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong_unmask, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong, unmask_tvb, offset, payload_length_32bit, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_pong, tvb, offset, payload_length_32bit, ENC_NA);
    }
    offset += payload_length_32bit;
    break;

    default: /* Unknown */
      ti = proto_tree_add_item(pl_tree, hf_ws_payload_unknown, tvb, offset, payload_length_32bit, ENC_NA);
      expert_add_info_format(pinfo, ti, PI_UNDECODED, PI_NOTE, "Dissector for Websocket Opcode (%d)"
                                       " code not implemented, Contact Wireshark developers"
                                       " if you want this supported", opcode);
    break;
  }
  return offset;
}
Beispiel #14
0
static int
dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    const char		*opcode_str;
    proto_tree		*slimp3_tree = NULL;
    proto_item		*ti = NULL, *hidden_item;
    gint		i1;
    gint		offset = 0;
    guint16		opcode;
    guchar		lcd_char;
    char		lcd_str[MAX_LCD_STR_LEN + 1];
    int			to_server = FALSE;
    int			old_protocol = FALSE;
    address		tmp_addr;
    gboolean		in_str;
    int			lcd_strlen;

    /*
     * If it doesn't begin with a known opcode, reject it, so that
     * traffic that happens to be do or from one of our ports
     * doesn't get misidentified as SliMP3 traffic.
     */
    if (!tvb_bytes_exist(tvb, offset, 1))
        return 0;	/* not even an opcode */
    opcode = tvb_get_guint8(tvb, offset);
    opcode_str = match_strval(opcode, slimp3_opcode_vals);
    if (opcode_str == NULL)
        return 0;

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

    if (check_col(pinfo->cinfo, COL_INFO)) {

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

    }

    if (tree) {

        ti = proto_tree_add_item(tree, proto_slimp3, tvb, offset, -1, ENC_NA);
        slimp3_tree = proto_item_add_subtree(ti, ett_slimp3);

        proto_tree_add_uint(slimp3_tree, hf_slimp3_opcode, tvb,
                            offset, 1, opcode);
    }

    /* The new protocol (v1.3 and later) uses an IANA-assigned port number.
    * It usually uses the same number for both sizes of the conversation, so
    * the port numbers can't always be used to determine client and server.
    * The new protocol places the clients MAC address in the packet, so that
    * is used to identify packets originating at the client.
    */
    if ((pinfo->destport == UDP_PORT_SLIMP3_V2) && (pinfo->srcport == UDP_PORT_SLIMP3_V2)) {
        SET_ADDRESS(&tmp_addr, AT_ETHER, 6, tvb_get_ptr(tvb, offset+12, 6));
        to_server = ADDRESSES_EQUAL(&tmp_addr, &pinfo->dl_src);
    }
    else if (pinfo->destport == UDP_PORT_SLIMP3_V2) {
        to_server = TRUE;
    }
    else if (pinfo->srcport == UDP_PORT_SLIMP3_V2) {
        to_server = FALSE;
    }
    if (pinfo->destport == UDP_PORT_SLIMP3_V1) {
        to_server = TRUE;
        old_protocol = TRUE;
    }
    else if (pinfo->srcport == UDP_PORT_SLIMP3_V1) {
        to_server = FALSE;
        old_protocol = TRUE;
    }

    switch (opcode) {

    case SLIMP3_IR:
        /* IR code
        *
        * [0]        'i' as in "IR"
        * [1]	     0x00
        * [2..5]     player's time since startup in ticks @625 KHz
        * [6]        IR code id, ff=JVC, 02=SLIMP3
        * [7]        number of meaningful bits - 16 for JVC, 32 for SLIMP3
        * [8..11]    the 32-bit IR code
        * [12..17]   reserved
        */
        if (tree) {
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_ir, tvb, offset+8, 4, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);

            i1 = tvb_get_ntohl(tvb, offset+2);
            proto_tree_add_text(slimp3_tree, tvb, offset+2, 4, "Uptime: %u sec (%u ticks)",
                                i1/625000, i1);
            i1 = tvb_get_guint8(tvb, offset+6);
            proto_tree_add_text(slimp3_tree, tvb, offset+6, 1, "Code identifier: 0x%0x: %s",
                                i1, val_to_str(i1, slimp3_ir_types, "Unknown"));
            proto_tree_add_text(slimp3_tree, tvb, offset+7, 1, "Code bits: %d",
                                tvb_get_guint8(tvb, offset+7));

            i1 = tvb_get_ntohl(tvb, offset+8);
            /* Check the code to figure out which remote is being used. */
            if (tvb_get_guint8(tvb, offset+6) == 0x02 &&
                    tvb_get_guint8(tvb, offset+7) == 32) {
                /* This is the custom SLIMP3 remote. */
                proto_tree_add_text(slimp3_tree, tvb, offset+8, 4,
                                    "Infrared Code: %s: 0x%0x",
                                    val_to_str(i1, slimp3_ir_codes_slimp3, "Unknown"), i1);
            }
            else if (tvb_get_guint8(tvb, offset+6) == 0xff &&
                     tvb_get_guint8(tvb, offset+7) == 16) {
                /* This is a JVC DVD player remote */
                proto_tree_add_text(slimp3_tree, tvb, offset+8, 4,
                                    "Infrared Code: %s: 0x%0x",
                                    val_to_str(i1, slimp3_ir_codes_jvc, "Unknown"), i1);
            } else {
                /* Unknown code; just write it */
                proto_tree_add_text(slimp3_tree, tvb, offset+8, 4, "Infrared Code: 0x%0x", i1);
            }
        }
        if (check_col(pinfo->cinfo, COL_INFO)) {
            i1 = tvb_get_ntohl(tvb, offset+8);
            if (tvb_get_guint8(tvb, offset+6) == 0x02 &&
                    tvb_get_guint8(tvb, offset+7) == 32) {
                col_append_fstr(pinfo->cinfo, COL_INFO, ", SLIMP3: %s",
                                val_to_str(i1, slimp3_ir_codes_slimp3, "Unknown (0x%0x)"));
            }
            else if (tvb_get_guint8(tvb, offset+6) == 0xff &&
                     tvb_get_guint8(tvb, offset+7) == 16) {
                col_append_fstr(pinfo->cinfo, COL_INFO, ", JVC: %s",
                                val_to_str(i1, slimp3_ir_codes_jvc, "Unknown (0x%0x)"));
            } else {
                /* Unknown code; just write it */
                col_append_fstr(pinfo->cinfo, COL_INFO, ", 0x%0x", i1);
            }
        }
        break;

    case SLIMP3_DISPLAY:
        if (tree) {

            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_display,
                                              tvb, offset, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);

            /* Loop through the commands */
            i1 = 18;
            in_str = FALSE;
            lcd_strlen = 0;
            while (i1 < tvb_reported_length_remaining(tvb, offset)) {
                switch(tvb_get_guint8(tvb, offset + i1)) {
                case 0:
                    in_str = FALSE;
                    lcd_strlen = 0;
                    proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
                                        "Delay (%d ms)", tvb_get_guint8(tvb, offset + i1 + 1));
                    i1 += 2;
                    break;
                case 3:
                    lcd_char = tvb_get_guint8(tvb, offset + i1 + 1);
                    if (!isprint(lcd_char)) lcd_char = '.';
                    if (ti && in_str) {
                        lcd_strlen += 2;
                        proto_item_append_text(ti, "%c", lcd_char);
                        proto_item_set_len(ti, lcd_strlen);
                    } else {
                        ti = proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
                                                 "String: %c", lcd_char);
                        in_str = TRUE;
                        lcd_strlen = 2;
                    }
                    i1 += 2;
                    break;

                case 2:
                    in_str = FALSE;
                    lcd_strlen = 0;
                    ti = proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
                                             "Command: %s",
                                             val_to_str(tvb_get_guint8(tvb, offset + i1 + 1),
                                                        slimp3_display_commands,
                                                        "Unknown (0x%0x)"));
                    if ((tvb_get_guint8(tvb, offset + i1 + 1) & 0xf0) == 0x30) {
                        proto_item_append_text(ti, ": %s",
                                               val_to_str(tvb_get_guint8(tvb, offset + i1 + 2),
                                                          slimp3_display_fset8,
                                                          "Unknown (0x%0x)"));
                        i1 += 2;
                    }
                    i1 += 2;
                    break;

                default:
                    proto_tree_add_text(slimp3_tree, tvb, offset + i1, 2,
                                        "Unknown 0x%0x, 0x%0x",
                                        tvb_get_guint8(tvb, offset + i1),
                                        tvb_get_guint8(tvb, offset + i1 + 1));
                    i1 += 2;
                    break;
                }
            }
        }

        if (check_col(pinfo->cinfo, COL_INFO)) {
            i1 = 18;
            lcd_strlen = 0;
            while (tvb_offset_exists(tvb, offset + i1) &&
                    lcd_strlen < MAX_LCD_STR_LEN) {
                switch (tvb_get_guint8(tvb, offset + i1)) {

                case 0:
                    lcd_str[lcd_strlen++] = '.';
                    break;

                case 2:
                    lcd_str[lcd_strlen++] = '|';
                    if (tvb_offset_exists(tvb, offset + i1 + 1) &&
                            (tvb_get_guint8(tvb, offset + i1 + 1) & 0xf0) == 0x30)
                        i1 += 2;
                    break;

                case 3:
                    if (tvb_offset_exists(tvb, offset + i1 + 1)) {
                        if (lcd_strlen < 1 ||
                                lcd_str[lcd_strlen-1] != ' ' ||
                                tvb_get_guint8(tvb, offset + i1 + 1) != ' ') {
                            lcd_char = tvb_get_guint8(tvb, offset + i1 + 1);
                            lcd_str[lcd_strlen++] = isprint(lcd_char) ? lcd_char : '.';
                        }
                    }
                }
                i1 += 2;
            }
            lcd_str[lcd_strlen] = '\0';
            if (lcd_strlen > 0)
                col_append_fstr(pinfo->cinfo, COL_INFO, ", %s", lcd_str);
        }

        break;

    case SLIMP3_CONTROL:
        if (tree) {
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_control,
                                              tvb, offset+1, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Command: %s",
                                val_to_str(tvb_get_guint8(tvb, offset+1),
                                           slimp3_stream_control, "Unknown (0x%0x)"));
        }

        if (check_col(pinfo->cinfo, COL_INFO)) {
            col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
                            val_to_str(tvb_get_guint8(tvb, offset+1),
                                       slimp3_stream_control, "Unknown (0x%0x)"));
        }
        break;

    case SLIMP3_HELLO:
        if (tree) {
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_hello,
                                              tvb, offset+1, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            if (to_server) {
                guint8 fw_ver = 0;
                /* Hello response; client->server */
                proto_tree_add_text(slimp3_tree, tvb, offset, 1, "Hello Response (Client --> Server)");
                proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Device ID: %d",
                                    tvb_get_guint8(tvb, offset+1));
                fw_ver = tvb_get_guint8(tvb, offset+2);
                proto_tree_add_text(slimp3_tree, tvb, offset+2, 1, "Firmware Revision: %d.%d (0x%0x)",
                                    fw_ver>>4, fw_ver & 0xf, fw_ver);
            } else {
                /* Hello request; server->client */
                proto_tree_add_text(slimp3_tree, tvb, offset, 1, "Hello Request (Server --> Client)");
            }
        }
        break;

    case SLIMP3_I2C:
        if (tree) {
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_i2c,
                                              tvb, offset, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            if (to_server) {
                /* Hello response; client->server */
                proto_tree_add_text(slimp3_tree, tvb, offset, -1,
                                    "I2C Response (Client --> Server)");
            } else {
                /* Hello request; server->client */
                proto_tree_add_text(slimp3_tree, tvb, offset, -1,
                                    "I2C Request (Server --> Client)");
            }
        }

        if (check_col(pinfo->cinfo, COL_INFO)) {
            if (to_server) {
                col_append_str(pinfo->cinfo, COL_INFO, ", Response");
            } else {
                col_append_str(pinfo->cinfo, COL_INFO, ", Request");
            }
        }
        break;

    case SLIMP3_DATA_REQ:
        if (tree) {
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_data_request,
                                              tvb, offset, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            proto_tree_add_text(slimp3_tree, tvb, offset+2, 2,
                                "Requested offset: %d bytes.",
                                tvb_get_ntohs(tvb, offset+2)*2);
        }

        if (check_col(pinfo->cinfo, COL_INFO)) {
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Offset: %d bytes",
                            tvb_get_ntohs(tvb, offset+2)*2);
        }
        break;

    case SLIMP3_DATA:
        /* MPEG data (v1.3 and later)
        *
        *  [0]       'm'
        *  [1..5]    reserved
        *  [6..7]    Write pointer (in words)
        *  [8..9]    reserved
        *  [10..11]  Sequence number
        *  [12..17]  reserved
        *  [18..]    MPEG data
        */
        if (tree) {
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_data,
                                              tvb, offset, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            if (old_protocol) {
                proto_tree_add_text(slimp3_tree, tvb, offset, -1,
                                    "Length: %d bytes",
                                    tvb_reported_length_remaining(tvb, offset+18));
                proto_tree_add_text(slimp3_tree, tvb, offset+2, 2,
                                    "Buffer offset: %d bytes.",
                                    tvb_get_ntohs(tvb, offset+2) * 2);
            }
            else {
                proto_tree_add_text(slimp3_tree, tvb, offset+1, 1, "Command: %s",
                                    val_to_str(tvb_get_guint8(tvb, offset+1),
                                               slimp3_mpg_control, "Unknown (0x%0x)"));
                proto_tree_add_text(slimp3_tree, tvb, offset, -1,
                                    "Length: %d bytes",
                                    tvb_reported_length_remaining(tvb, offset+18));
                proto_tree_add_text(slimp3_tree, tvb, offset+6, 2,
                                    "Write Pointer: %d",
                                    tvb_get_ntohs(tvb, offset+6) * 2);
                proto_tree_add_text(slimp3_tree, tvb, offset+10, 2,
                                    "Sequence: %d",
                                    tvb_get_ntohs(tvb, offset+10));
            }
        }

        if (check_col(pinfo->cinfo, COL_INFO)) {
            if (old_protocol) {
                col_append_fstr(pinfo->cinfo, COL_INFO,
                                ", Length: %d bytes, Offset: %d bytes.",
                                tvb_reported_length_remaining(tvb, offset+18),
                                tvb_get_ntohs(tvb, offset+2) * 2);
            }
            else {
                col_append_fstr(pinfo->cinfo, COL_INFO,
                                ", %s, %d bytes at %d, Sequence: %d",
                                val_to_str(tvb_get_guint8(tvb, offset+1),
                                           slimp3_mpg_control, "Unknown (0x%0x)"),
                                tvb_reported_length_remaining(tvb, offset+18),
                                tvb_get_ntohs(tvb, offset+6) * 2,
                                tvb_get_ntohs(tvb, offset+10));
            }
        }
        break;

    case SLIMP3_DISC_REQ:
        if (tree) {
            guint8 fw_ver;
            hidden_item = proto_tree_add_item(slimp3_tree, hf_slimp3_discover_request,
                                              tvb, offset, 1, ENC_BIG_ENDIAN);
            PROTO_ITEM_SET_HIDDEN(hidden_item);
            proto_tree_add_text(slimp3_tree, tvb, offset+1, 1,
                                "Device ID: %d.", tvb_get_guint8(tvb, offset+1));
            fw_ver = tvb_get_guint8(tvb, offset+2);
            proto_tree_add_text(slimp3_tree, tvb, offset+2, 1, "Firmware Revision: %d.%d (0x%0x)",
                                fw_ver>>4, fw_ver & 0xf, fw_ver);
        }

        if (check_col(pinfo->cinfo, COL_INFO)) {
            guint8 fw_ver = tvb_get_guint8(tvb, offset+2);
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Device ID: %d. Firmware: %d.%d",
                            tvb_get_guint8(tvb, offset+1), fw_ver>>4, fw_ver & 0xf);
        }
Beispiel #15
0
static void
dissect_mtp3_routing_label(tvbuff_t *tvb, packet_info *pinfo, proto_tree *mtp3_tree)
{
  guint32 label, dpc, opc;
  proto_item *label_item, *label_dpc_item, *label_opc_item;
  proto_item *hidden_item;
  proto_tree *label_tree;
  proto_tree *pc_subtree;
  int hf_dpc_string;
  int hf_opc_string;


  switch (mtp3_standard) {
  case ITU_STANDARD:
    label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, "Routing label");
    label_tree = proto_item_add_subtree(label_item, ett_mtp3_label);

    label = tvb_get_letohl(tvb, ROUTING_LABEL_OFFSET);

    opc = (label & ITU_OPC_MASK) >> 14;
    dpc =  label & ITU_DPC_MASK;

    hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc);
    PROTO_ITEM_SET_HIDDEN(hidden_item);
    hidden_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_pc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc);
    PROTO_ITEM_SET_HIDDEN(hidden_item);

    label_dpc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_dpc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label);
    if (mtp3_pc_structured())
      proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc));

    if(mtp3_addr_dpc->ni == MTP3_NI_INT0) {
      pc_subtree = proto_item_add_subtree(label_dpc_item, ett_mtp3_label_dpc);
      analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, dpc);
    }


    label_opc_item = proto_tree_add_uint(label_tree, hf_mtp3_itu_opc, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label);
    if (mtp3_pc_structured())
      proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc));

    if(mtp3_addr_opc->ni == MTP3_NI_INT0) {
      pc_subtree = proto_item_add_subtree(label_opc_item, ett_mtp3_label_opc);
      analyze_q708_ispc(tvb, pc_subtree, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, opc);
    }

    proto_tree_add_uint(label_tree, hf_mtp3_itu_sls, tvb, ROUTING_LABEL_OFFSET, ITU_ROUTING_LABEL_LENGTH, label);
    break;

  case ANSI_STANDARD:
  case CHINESE_ITU_STANDARD:
    if (mtp3_standard == ANSI_STANDARD)
    {
      hf_dpc_string = hf_mtp3_ansi_dpc;
      hf_opc_string = hf_mtp3_ansi_opc;
    } else /* CHINESE_ITU_STANDARD */ {
      hf_dpc_string = hf_mtp3_chinese_dpc;
      hf_opc_string = hf_mtp3_chinese_opc;
    }

    /* Create the Routing Label Tree */
    label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, ANSI_ROUTING_LABEL_LENGTH, "Routing label");
    label_tree = proto_item_add_subtree(label_item, ett_mtp3_label);


    /* create and fill the DPC tree */
    dissect_mtp3_3byte_pc(tvb, ANSI_DPC_OFFSET, label_tree, ett_mtp3_label_dpc, hf_dpc_string, hf_mtp3_dpc_network,
			  hf_mtp3_dpc_cluster, hf_mtp3_dpc_member, hf_mtp3_24bit_dpc, hf_mtp3_24bit_pc);
    /* Store dpc for mtp3_addr below */
    dpc = tvb_get_letoh24(tvb, ANSI_DPC_OFFSET);

    /* create and fill the OPC tree */
    dissect_mtp3_3byte_pc(tvb, ANSI_OPC_OFFSET, label_tree, ett_mtp3_label_opc, hf_opc_string, hf_mtp3_opc_network,
			  hf_mtp3_opc_cluster, hf_mtp3_opc_member, hf_mtp3_24bit_opc, hf_mtp3_24bit_pc);
    /* Store opc for mtp3_addr below */
    opc = tvb_get_letoh24(tvb, ANSI_OPC_OFFSET);

    /* SLS */
    if (mtp3_standard == ANSI_STANDARD) {
      if (mtp3_use_ansi_5_bit_sls)
	proto_tree_add_item(label_tree, hf_mtp3_ansi_5_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA);
      else
	proto_tree_add_item(label_tree, hf_mtp3_ansi_8_bit_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA);
    } else /* CHINESE_ITU_STANDARD */ {
      proto_tree_add_item(label_tree, hf_mtp3_chinese_itu_sls, tvb, ANSI_SLS_OFFSET, SLS_LENGTH, ENC_NA);
    }
    break;

  case JAPAN_STANDARD:
    label_item = proto_tree_add_text(mtp3_tree, tvb, ROUTING_LABEL_OFFSET, JAPAN_ROUTING_LABEL_LENGTH, "Routing label");
    label_tree = proto_item_add_subtree(label_item, ett_mtp3_label);

    label_dpc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_dpc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
    dpc = tvb_get_letohs(tvb, ROUTING_LABEL_OFFSET);
    if (mtp3_pc_structured()) {
      proto_item_append_text(label_dpc_item, " (%s)", mtp3_pc_to_str(dpc));
    }

    label_opc_item = proto_tree_add_item(label_tree, hf_mtp3_japan_opc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
    opc = tvb_get_letohs(tvb, JAPAN_OPC_OFFSET);
    if (mtp3_pc_structured()) {
      proto_item_append_text(label_opc_item, " (%s)", mtp3_pc_to_str(opc));
    }

    hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, ROUTING_LABEL_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
    PROTO_ITEM_SET_HIDDEN(hidden_item);
    hidden_item = proto_tree_add_item(label_tree, hf_mtp3_japan_pc, tvb, JAPAN_OPC_OFFSET, JAPAN_PC_LENGTH, ENC_LITTLE_ENDIAN);
    PROTO_ITEM_SET_HIDDEN(hidden_item);

    if (mtp3_use_japan_5_bit_sls) {
	proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA);
	proto_tree_add_item(label_tree, hf_mtp3_japan_5_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA);
    } else {
	proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA);
	proto_tree_add_item(label_tree, hf_mtp3_japan_4_bit_sls_spare, tvb, JAPAN_SLS_OFFSET, JAPAN_SLS_SPARE_LENGTH, ENC_NA);
    }

    break;
  default:
    DISSECTOR_ASSERT_NOT_REACHED();
  }

  mtp3_addr_opc->type = (Standard_Type)mtp3_standard;
  mtp3_addr_opc->pc = opc;
  SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc);

  mtp3_addr_dpc->type = (Standard_Type)mtp3_standard;
  mtp3_addr_dpc->pc = dpc;
  SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc);
}
static void
display_socks_v5(tvbuff_t *tvb, int offset, packet_info *pinfo,
	proto_tree *tree, socks_hash_entry_t *hash_info) {

/* Display the protocol tree for the version. This routine uses the	*/
/* stored conversation information to decide what to do with the row.	*/
/* Per packet information would have been better to do this, but we	*/
/* didn't have that when I wrote this. And I didn't expect this to get	*/
/* so messy.								*/

	unsigned int i, command;
	guint temp;
	const char *AuthMethodStr;
	guint8 auth_status;

	proto_tree_add_item( tree, hf_socks_ver, tvb, offset, 1, FALSE);
	++offset;

	if (compare_packet( hash_info->connect_row)){

		proto_tree      *AuthTree;
		proto_item      *ti;

		temp = tvb_get_guint8(tvb, offset);	/* Get Auth method count */
							/* build auth tree */
		ti = proto_tree_add_text( tree, tvb, offset, -1,
				"Client Authentication Methods");

		AuthTree = proto_item_add_subtree(ti, ett_socks_auth);

		proto_tree_add_text( AuthTree, tvb, offset, 1,
				"Count: %u", temp);
		++offset;

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

			AuthMethodStr = get_auth_method_name(
				tvb_get_guint8( tvb, offset));
			proto_tree_add_text( AuthTree, tvb, offset, 1,
				"Method[%u]: %u (%s)", i,
				tvb_get_guint8( tvb, offset), AuthMethodStr);
			++offset;
		}
		proto_item_set_end( ti, tvb, offset);
		return;
	}					/* Get accepted auth method */
	else if (compare_packet( hash_info->auth_method_row)) {

		proto_tree_add_text( tree, tvb, offset, 1,
			"Accepted Auth Method: 0x%0x (%s)", tvb_get_guint8( tvb, offset),
				get_auth_method_name( tvb_get_guint8( tvb, offset)));

		return;
	}					/* handle user/password auth */
	else if (compare_packet( hash_info->user_name_auth_row)) {

						/* process user name	*/
		offset += display_string( tvb, offset, tree,
				"User name");
						/* process password	*/
		offset += display_string( tvb, offset, tree,
				"Password");
	}
					/* command to the server */
					/* command response from server */
	else if (compare_packet( hash_info->auth_version)) {
		auth_status = tvb_get_guint8(tvb, offset);
		if(auth_status != 0)
			proto_tree_add_text( tree, tvb, offset, 1, "Status: %u (failure)", auth_status);
		else
			proto_tree_add_text( tree, tvb, offset, 1, "Status: success");
		offset ++;
	}
	else if (compare_packet( hash_info->gssapi_auth_row)) {
		guint16 len;
		proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, FALSE);
		proto_tree_add_item( tree, hf_gssapi_length, tvb, offset+1, 2, FALSE);
		len = tvb_get_ntohs(tvb, offset+1);
		if (len > 0)
			proto_tree_add_item( tree, hf_gssapi_payload, tvb, offset+3, len, FALSE);
	}
	else if (compare_packet( hash_info->gssapi_auth_failure_row)) {
		proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, FALSE);
	}
	else if (compare_packet( hash_info->gssapi_auth_reply_row)) {
		guint16 len;
		proto_tree_add_item( tree, hf_gssapi_command, tvb, offset, 1, FALSE);
		proto_tree_add_item( tree, hf_gssapi_length, tvb, offset+1, 2, FALSE);
		len = tvb_get_ntohs(tvb, offset+1);
		if (len > 0)
			proto_tree_add_item( tree, hf_gssapi_payload, tvb, offset+3, len, FALSE);
	}
	else if ((compare_packet( hash_info->command_row)) ||
	         (compare_packet( hash_info->cmd_reply_row)) ||
	         (compare_packet( hash_info->bind_reply_row))){

		command = tvb_get_guint8(tvb, offset);

		if (compare_packet( hash_info->command_row))
			proto_tree_add_uint( tree, hf_socks_cmd, tvb, offset, 1,
			    command);

		else {
			proto_item *hidden_item;
			proto_tree_add_item( tree, hf_socks_results_5, tvb, offset, 1, FALSE);
			hidden_item = proto_tree_add_item(tree, hf_socks_results, tvb, offset, 1, FALSE);
			PROTO_ITEM_SET_HIDDEN(hidden_item);
		}

		++offset;

		proto_tree_add_text( tree, tvb, offset, 1,
			"Reserved: 0x%0x (should = 0x00)", tvb_get_guint8(tvb, offset));
		++offset;

		offset = display_address(tvb, offset, tree);
/*XXX Add remote port for search somehow */
						/* Do remote port	*/
		proto_tree_add_text( tree, tvb, offset, 2,
				"%sPort: %u",
				(compare_packet( hash_info->bind_reply_row) ?
					"Remote Host " : ""),
				 tvb_get_ntohs(tvb, offset));
	}
}
Beispiel #17
0
static void
dissect_xmpp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {

    xml_frame_t *xml_frame;
    gboolean     out_packet;

    conversation_t   *conversation;
    xmpp_conv_info_t *xmpp_info;

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

    xmpp_element_t *packet = NULL;

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

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

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

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

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

    col_clear(pinfo->cinfo, COL_INFO);

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

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

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

    call_dissector(xml_handle, tvb, pinfo, xmpp_tree);

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

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

    if(!pinfo->private_data)
        return;

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

    if(!xml_frame)
        return;

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

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

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

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

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

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

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

            PROTO_ITEM_SET_HIDDEN(outin_item);


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

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

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

        xmpp_element_t_tree_free(packet);
        xml_frame = xml_frame->next_sibling;
    }
}
static void
dissect_gift(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item	*ti, *hidden_item;
	proto_tree	*gift_tree, *cmd_tree;
	gboolean	is_request;
	gint            offset = 0;
	const guchar    *line;
	gint            next_offset;
	int             linelen;
	int             tokenlen;
	const guchar    *next_token;

	/* set "Protocol" column text */
	col_set_str(pinfo->cinfo, COL_PROTOCOL, "giFT");

	/* determine whether it is a request to or response from the server */
	if (pinfo->match_uint == pinfo->destport)
		is_request = TRUE;
	else
		is_request = FALSE;

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

	/* set "Info" column text */
	col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s",
			     is_request ? "Request" : "Response",
			     format_text(line, linelen));

	/* if tree != NULL, build protocol tree */
	if (tree) {
		ti = proto_tree_add_item(tree, proto_gift, tvb, 0, -1, ENC_NA);
		gift_tree = proto_item_add_subtree(ti, ett_gift);

		if (is_request) {
			hidden_item = proto_tree_add_boolean(gift_tree, hf_gift_request, tvb, 0, 0, TRUE);
		} else {
			hidden_item = proto_tree_add_boolean(gift_tree, hf_gift_response, tvb, 0, 0, TRUE);
		}
		PROTO_ITEM_SET_HIDDEN(hidden_item);

		ti = proto_tree_add_format_text(gift_tree, tvb, offset, next_offset - offset);
		cmd_tree = proto_item_add_subtree(ti, ett_gift_cmd);

		tokenlen = get_token_len(line, line + linelen, &next_token);
		if (tokenlen != 0) {
			if (is_request) {
				proto_tree_add_string(cmd_tree, hf_gift_request_cmd, tvb, offset,
						    tokenlen, format_text(line, tokenlen));
			} else {
				proto_tree_add_string(cmd_tree, hf_gift_response_cmd, tvb, offset,
						    tokenlen, format_text(line, tokenlen));
			}
			offset += (gint) (next_token - line);
			linelen -= (int) (next_token - line);
			line = next_token;
		}

		if (linelen != 0) {
			if (is_request) {
				proto_tree_add_string(cmd_tree, hf_gift_request_arg, tvb, offset,
						    linelen, format_text(line, linelen));
			} else {
				proto_tree_add_string(cmd_tree, hf_gift_response_arg, tvb, offset,
						    linelen, format_text(line, linelen));
			}
		}
	}
}
Beispiel #19
0
/* XXX: Are all the tests against tvb_length() really the right way to handle invalid fields ?
 *      It seems to me that invalid fields should just add an expert item
 *        or cause a "Malformed" exception.
 */
static void
dissect_elcom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
        gboolean    is_request, length_ok;
        proto_tree *elcom_tree;
        proto_item *ti, *hidden_item;
        gint        offset = 0;
        guint       elcom_len;
        guint8      elcom_msg_type;
        guint8     *suffix;

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

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

        is_request = (pinfo->match_uint == pinfo->destport);
        elcom_len  = tvb_get_ntohs(tvb, 0);
        length_ok  = (tvb_reported_length(tvb) == (elcom_len+2));

        col_add_fstr(pinfo->cinfo, COL_INFO, "%s Len=%d%s",
                             is_request ? "Request" : "Response",
                             elcom_len,
                             length_ok ? "" : " (incorrect)");

        elcom_msg_type = tvb_get_guint8(tvb, 2);
        switch (elcom_msg_type) {
                case P_CONRQ:
                case P_CONRS:

                        /* starting after elcom_len and elcom_msg_type,
                           initiator + responder + userdata fields must be there */
                        if (tvb_length_remaining(tvb, 3+TOTAL_LEN+TOTAL_LEN+3) < 0) return;
                        /* check also that those field lengths are valid */
                        if (tvb_get_guint8(tvb, 3)  != LOWADR_LEN) return;
                        if (tvb_get_guint8(tvb, 3+1+LOWADR_LEN) != SUFFIX_LEN) return;
                        if (tvb_get_guint8(tvb, 3+TOTAL_LEN) != LOWADR_LEN) return;
                        if (tvb_get_guint8(tvb, 3+1+TOTAL_LEN+LOWADR_LEN) != SUFFIX_LEN) return;

                        /* finally believe that there is valid suffix */
                        suffix = tvb_get_string_enc(wmem_packet_scope(), tvb, 3+2+LOWADR_LEN, 2, ENC_ASCII);
                        col_append_fstr(pinfo->cinfo, COL_INFO, " %s Connect", suffix);
                        break;

                case P_RELRQ:
                case P_RELRS:
                        col_append_str(pinfo->cinfo, COL_INFO, " Release");
                        break;

                case P_DATRQ:
                        col_append_str(pinfo->cinfo, COL_INFO, " Data");
                        break;
                }

                switch (elcom_msg_type) {
                case P_CONRQ:
                case P_RELRQ:
                        col_append_str(pinfo->cinfo, COL_INFO, " Request");
                        break;

                case P_CONRS:
                case P_RELRS:
                        col_append_str(pinfo->cinfo, COL_INFO, " Response");
                        break;
        }

        if (!tree)
                return;

        ti = proto_tree_add_item(tree, proto_elcom, tvb, offset, -1, ENC_NA);
        elcom_tree = proto_item_add_subtree(ti, ett_elcom);

        hidden_item = proto_tree_add_boolean(elcom_tree,
                                             is_request ? hf_elcom_request : hf_elcom_response,
                                             tvb, 0, 0, TRUE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);

        /* 2 first bytes are the frame length */
        offset = 0;
        ti = proto_tree_add_item(elcom_tree, hf_elcom_length, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset = +2;
        if (! length_ok) {
                proto_item_append_text(ti, " (incorrect)");
        }

        elcom_msg_type = tvb_get_guint8(tvb, offset);
        ti = proto_tree_add_item(elcom_tree, hf_elcom_type, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_item_append_text(elcom_tree, " ( %s)", val_to_str(elcom_msg_type, type_vals, "Unknown %d"));

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

        switch (elcom_msg_type) {
        case P_CONRQ:
        case P_CONRS:
                /*
                 * Connection request/release assiciated PDU's,
                 * /ELCOM-90 P Protocol spec/ p. 85...
                 */

                /* We need the length here, hardcode the LOWADR_LEN = 21 */
                ti = proto_tree_add_item(elcom_tree, hf_elcom_initiator, tvb, offset, TOTAL_LEN, ENC_NA);
                offset = dissect_lower_address(ti, ett_elcom_initiator, tvb, offset,
                                               hf_elcom_initiator_endian,
                                               hf_elcom_initiator_ip,
                                               hf_elcom_initiator_port,
                                               hf_elcom_initiator_suff);
                if (tvb_length_remaining(tvb, offset) <= 0)
                        return;

                ti = proto_tree_add_item(elcom_tree, hf_elcom_responder, tvb, offset, TOTAL_LEN, ENC_NA);
                offset = dissect_lower_address(ti, ett_elcom_responder, tvb, offset,
                                               hf_elcom_responder_endian,
                                               hf_elcom_responder_ip,
                                               hf_elcom_responder_port,
                                               hf_elcom_responder_suff);
                if (tvb_length_remaining(tvb, offset) <= 0)
                        return;

                /* Rest of the payload is USER-DATA, 0..82 bytes */
                ti = proto_tree_add_item(elcom_tree, hf_elcom_userdata, tvb, offset, -1, ENC_NA);
                offset = dissect_userdata(ti, ett_elcom_userdata, tvb, offset);

                break;

        case P_RELRQ:

                proto_tree_add_item(elcom_tree, hf_elcom_release_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                break;
        case P_RELRS:

                proto_tree_add_item(elcom_tree, hf_elcom_release_result, tvb, offset, 1, ENC_BIG_ENDIAN);

                offset += 1;

                break;

        case P_DATRQ:
                ti = proto_tree_add_item(elcom_tree, hf_elcom_datarequest, tvb, offset, -1, ENC_NA);
                offset = dissect_datarequest(ti, ett_elcom_datarequest, tvb, offset);
                break;

        default:
                proto_item_append_text(ti, " <<--- meaning WHAT??");
                break;
        }

        if (tvb_length_remaining(tvb, offset) > 0)
        {
            /* We should not get here, but if we do, show what is left over: */
            proto_tree_add_item(elcom_tree, hf_elcom_strangeleftover, tvb, offset, -1, ENC_NA);
        }
}
Beispiel #20
0
/*
 * 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");

	if (check_col(pinfo->cinfo, COL_INFO)) {
		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_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:
		if (check_col(pinfo->cinfo, COL_INFO)) {
			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:
		if (check_col(pinfo->cinfo, COL_INFO)) {
			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)");

		if (check_col(pinfo->cinfo, COL_INFO)) {
			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(pgm_tree, hf_pgm_main_opts, tvb,
			ptvcursor_current_offset(cursor), 1, pgmhdr_opts, "Options: %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(pgm_tree, hf_pgm_main_cksum, tvb,
				ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: 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(pgm_tree, hf_pgm_main_cksum, tvb,
						ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: 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(pgm_tree, hf_pgm_main_cksum, tvb,
					    ptvcursor_current_offset(cursor), 2, pgmhdr_cksum, "Checksum: 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));
			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:
				proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				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));
			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:
				proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

			afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			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:
				proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				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));
			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:
				proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				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, pktname);

		if (isdata)
			decode_pgm_ports(tvb, ptvcursor_current_offset(cursor), pinfo, tree, pgmhdr_sport, pgmhdr_dport);
	}
}
Beispiel #21
0
static
void dissect_pw_satop(tvbuff_t * tvb_original
					,packet_info * pinfo
					,proto_tree * tree
					,pwc_demux_type_t demux)
{
	const int encaps_size = 4; /*RTP header in encapsulation is not supported yet*/
	gint      packet_size;
	gint      payload_size;
	gint      padding_size;
	int properties;

	enum {
		PAY_NO_IDEA = 0
		,PAY_LIKE_E1
		,PAY_LIKE_T1
		,PAY_LIKE_E3_T3
		,PAY_LIKE_OCTET_ALIGNED_T1
	} payload_properties;

	packet_size = tvb_reported_length_remaining(tvb_original, 0);
	/*
	 * FIXME
	 * "4" below should be replaced by something like "min_packet_size_this_dissector"
	 * Also call to dissect_try_cw_first_nibble() should be moved before this block
	 */
	if (packet_size < 4) /* 4 is smallest size which may be sensible (for PWACH dissector) */
	{
		proto_item  *item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		expert_add_info_format(pinfo, item, &ei_cw_packet_size_too_small,
				       "PW packet size (%d) is too small to carry sensible information"
				       ,(int)packet_size);
		col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
		col_set_str(pinfo->cinfo, COL_INFO, "Malformed: PW packet is too small");
		return;
	}

	switch (demux)
	{
	case PWC_DEMUX_MPLS:
		if (dissect_try_cw_first_nibble(tvb_original, pinfo, tree))
		{
			return;
		}
		break;
	case PWC_DEMUX_UDP:
		break;
	default:
		DISSECTOR_ASSERT_NOT_REACHED();
		return;
	}

	/* check how "good" is this packet */
	/* also decide payload length from packet size and CW */
	properties = 0;
	if (0 != (tvb_get_guint8(tvb_original, 0) & 0xf0 /*bits03*/))
	{
		properties |= PWC_CW_BAD_BITS03;
	}
	if (0 != (tvb_get_guint8(tvb_original, 0) & 0x03 /*rsv*/))
	{
		properties |= PWC_CW_BAD_RSV;
	}
	if (0 != (tvb_get_guint8(tvb_original, 1) & 0xc0 /*frag*/))
	{
		properties |= PWC_CW_BAD_FRAG;
	}
	{
		/* RFC4553:
		 * [...MAY be used to carry the length of the SAToP
		 * packet (defined as the size of the SAToP header + the payload
		 * size) if it is less than 64 bytes, and MUST be set to zero
		 * otherwise... ]
		 *
		 * Note that this differs from RFC4385's definition of length:
		 * [ If the MPLS payload is less than 64 bytes, the length field
		 * MUST be set to the length of the PW payload...]
		 *
		 * We will use RFC4553's definition here.
		 */
		int  cw_len;
		gint payload_size_from_packet;

		cw_len = tvb_get_guint8(tvb_original, 1) & 0x3f;
		payload_size_from_packet = packet_size - encaps_size;
		if (cw_len != 0)
		{
			gint payload_size_from_cw;
			payload_size_from_cw = cw_len - encaps_size;
			/*
			 * Assumptions for error case,
			 * will be overwritten if no errors found:
			 */
			payload_size = payload_size_from_packet;
			padding_size = 0;

			if (payload_size_from_cw < 0)
			{
				properties |= PWC_CW_BAD_PAYLEN_LT_0;
			}
			else if (payload_size_from_cw > payload_size_from_packet)
			{
				properties |= PWC_CW_BAD_PAYLEN_GT_PACKET;
			}
			else if (payload_size_from_packet >= 64)
			{
				properties |= PWC_CW_BAD_LEN_MUST_BE_0;
			}
			else /* ok */
			{
				payload_size = payload_size_from_cw;
				padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
			}
		}
		else
		{
			payload_size = payload_size_from_packet;
			padding_size = 0;
		}
	}
	if (payload_size == 0)
	{
		/*
		 * As CW.L it indicates that PW payload is invalid, dissector should
		 * not blame packets with bad payload (including "bad" or "strange" SIZE of
		 * payload) when L bit is set.
		 */
		if (0 == (tvb_get_guint8(tvb_original, 0) & 0x08 /*L bit*/))
		{
			properties |= PWC_PAY_SIZE_BAD;
		}
	}

	/* guess about payload type */
	if (payload_size == 256)
	{
		payload_properties = PAY_LIKE_E1;
	}
	else if (payload_size == 192)
	{
		payload_properties = PAY_LIKE_T1;
	}
	else if (payload_size == 1024)
	{
		payload_properties = PAY_LIKE_E3_T3;
	}
	else if ((payload_size != 0) && (payload_size % 25 == 0))
	{
		payload_properties = PAY_LIKE_OCTET_ALIGNED_T1;
	}
	else
	{
		payload_properties = PAY_NO_IDEA; /*we do not have any ideas about payload type*/
	}

	/* fill up columns*/
	col_set_str(pinfo->cinfo, COL_PROTOCOL, shortname);
	col_clear(pinfo->cinfo, COL_INFO);
	if (properties & PWC_ANYOF_CW_BAD)
	{
		col_set_str(pinfo->cinfo, COL_INFO, "CW:Bad, ");
	}

	if (properties & PWC_PAY_SIZE_BAD)
	{
		col_append_str(pinfo->cinfo, COL_INFO, "Payload size:0 (Bad)");
	}
	else
	{
		col_append_fstr(pinfo->cinfo, COL_INFO, "TDM octets:%d", (int)payload_size);
	}

	if (padding_size != 0)
	{
		col_append_fstr(pinfo->cinfo, COL_INFO, ", Padding:%d", (int)padding_size);
	}


	{
		proto_item* item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		pwc_item_append_cw(item,tvb_get_ntohl(tvb_original, 0),TRUE);
		pwc_item_append_text_n_items(item,(int)payload_size,"octet");
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				proto_item* item2;
				tvb = tvb_new_subset_length(tvb_original, 0, PWC_SIZEOF_CW);
				item2 = proto_tree_add_item(tree2, hf_cw, tvb, 0, -1, ENC_NA);
				pwc_item_append_cw(item2, tvb_get_ntohl(tvb, 0),FALSE);
				{
					proto_tree* tree3;
					tree3 = proto_item_add_subtree(item2, ett);
					{
						proto_item* item3;
						if (properties & PWC_CW_BAD_BITS03) /*display only if value is wrong*/
						{
							item3 = proto_tree_add_item(tree3, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN);
							expert_add_info(pinfo, item3, &ei_cw_bits03);
						}

						proto_tree_add_item(tree3, hf_cw_l  , tvb, 0, 1, ENC_BIG_ENDIAN);
						proto_tree_add_item(tree3, hf_cw_r  , tvb, 0, 1, ENC_BIG_ENDIAN);

						item3 = proto_tree_add_item(tree3, hf_cw_rsv, tvb, 0, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_RSV)
						{
							expert_add_info(pinfo, item3, &ei_cw_rsv);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_frg, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_FRAG)
						{
							expert_add_info(pinfo, item3, &ei_cw_frg);
						}

						item3 = proto_tree_add_item(tree3, hf_cw_len, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_PAYLEN_LT_0)
						{
							expert_add_info_format(pinfo, item3, &ei_payload_size_invalid,
								"Bad Length: too small, must be > %d",
								(int)encaps_size);
						}
						if (properties & PWC_CW_BAD_PAYLEN_GT_PACKET)
						{
							expert_add_info_format(pinfo, item3, &ei_payload_size_invalid,
								"Bad Length: must be <= than PSN packet size (%d)",
								(int)packet_size);
						}
						if (properties & PWC_CW_BAD_LEN_MUST_BE_0)
						{
							expert_add_info_format(pinfo, item3, &ei_payload_size_invalid,
								"Bad Length: must be 0 if SAToP packet size (%d) is > 64",
								(int)packet_size);
						}

						proto_tree_add_item(tree3, hf_cw_seq, tvb, 2, 2, ENC_BIG_ENDIAN);
					}
				}
			}
		}

		/* payload */
		if (properties & PWC_PAY_SIZE_BAD)
		{
			expert_add_info_format(pinfo, item, &ei_payload_size_invalid,
				"SAToP payload: none found. Size of payload must be <> 0");
		}
		else if (payload_size == 0)
		{
			expert_add_info(pinfo, item, &ei_payload_size_invalid_undecoded);
		}
		else
		{

			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				proto_item* item2;
				tvbuff_t* tvb;
				tvb = tvb_new_subset_length(tvb_original, PWC_SIZEOF_CW, payload_size);
				item2 = proto_tree_add_item(tree2, hf_payload, tvb, 0, -1, ENC_NA);
				pwc_item_append_text_n_items(item2,(int)payload_size,"octet");
				{
					proto_tree* tree3;
					const char* s;
					switch(payload_properties)
					{
					case PAY_LIKE_E1:
						s = " (looks like E1)";
						break;
					case PAY_LIKE_T1:
						s = " (looks like T1)";
						break;
					case PAY_LIKE_E3_T3:
						s = " (looks like E3/T3)";
						break;
					case PAY_LIKE_OCTET_ALIGNED_T1:
						s = " (looks like octet-aligned T1)";
						break;
					case PAY_NO_IDEA:
					default:
						s = "";
						break;
					}
					proto_item_append_text(item2, "%s", s);
					tree3 = proto_item_add_subtree(item2, ett);
					call_dissector(data_handle, tvb, pinfo, tree3);
					item2 = proto_tree_add_int(tree3, hf_payload_l, tvb, 0, 0
						,(int)payload_size); /* allow filtering */
					PROTO_ITEM_SET_HIDDEN(item2);
				}
			}
		}

		/* padding */
		if (padding_size > 0)
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW + payload_size, padding_size, -1);
				call_dissector(pw_padding_handle, tvb, pinfo, tree2);
			}
		}
	}
	return;
}
Beispiel #22
0
/* Header */
static void
dissect_cpfi_header(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint32 tda;
  guint32 src;
  guint8 src_instance = 0;
  guint8 src_board = 0;
  guint8 src_port = 0;
  guint32 dst;
  guint8 dst_instance = 0;
  guint8 dst_board = 0;
  guint8 dst_port = 0;
  proto_item *extra_item = NULL;
  proto_tree *extra_tree = NULL;
  proto_item *hidden_item;

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

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

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

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

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

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

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

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

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

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

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

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

    /* add word 2 components to the protocol tree */
    proto_tree_add_item(extra_tree, hf_cpfi_word_two  , tvb, 4, 4, ENC_BIG_ENDIAN);
  };
}
Beispiel #23
0
static void
dissect_fcp_cmnd(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, proto_tree *tree, conversation_t *conversation, fc_hdr *fchdr, fcp_conv_data_t *fcp_conv_data)
{
    int          offset  = 0;
    int          add_len = 0;
    guint8       flags, rwflags, lun0;
    guint16      lun     = 0xffff;
    tvbuff_t    *cdb_tvb;
    int          tvb_len, tvb_rlen;
    fcp_request_data_t *request_data = NULL;
    proto_item  *hidden_item;
    fcp_proto_data_t *proto_data;

    /* Determine the length of the FCP part of the packet */
    flags = tvb_get_guint8(tvb, offset+10);
    if (flags) {
        add_len = tvb_get_guint8(tvb, offset+11) & 0x7C;
        add_len = add_len >> 2;
    }

    hidden_item = proto_tree_add_uint(tree, hf_fcp_type, tvb, offset, 0, 0);
    PROTO_ITEM_SET_HIDDEN(hidden_item);

    lun0 = tvb_get_guint8(tvb, offset);

    /* Display single-level LUNs in decimal for clarity */
    /* I'm taking a shortcut here by assuming that if the first byte of the
     * LUN field is 0, it is a single-level LUN. This is not true. For a
     * real single-level LUN, all 8 bytes except byte 1 must be 0.
     */
    if (lun0) {
      proto_tree_add_item(tree, hf_fcp_multilun, tvb, offset, 8, ENC_NA);
      lun = tvb_get_guint8(tvb, offset) & 0x3f;
      lun <<= 8;
      lun |= tvb_get_guint8(tvb, offset+1);
    } else {
      proto_tree_add_item(tree, hf_fcp_singlelun, tvb, offset+1,
                          1, ENC_BIG_ENDIAN);
      lun = tvb_get_guint8(tvb, offset+1);
    }

    if (fchdr->itlq)
        fchdr->itlq->lun = lun;

    if (!pinfo->fd->flags.visited) {
        proto_data = wmem_new(wmem_file_scope(), fcp_proto_data_t);
        proto_data->lun = lun;
        p_add_proto_data(wmem_file_scope(), pinfo, proto_fcp, 0, proto_data);
    }

    request_data = (fcp_request_data_t*)wmem_tree_lookup32(fcp_conv_data->luns, lun);
    if (!request_data) {
        request_data = wmem_new(wmem_file_scope(), fcp_request_data_t);
        request_data->request_frame = pinfo->fd->num;
        request_data->response_frame = 0;
        request_data->request_time = pinfo->fd->abs_ts;
        request_data->itl = wmem_new(wmem_file_scope(), itl_nexus_t);
        request_data->itl->cmdset = 0xff;
        request_data->itl->conversation = conversation;
        wmem_tree_insert32(fcp_conv_data->luns, lun, request_data);
    }

    proto_tree_add_item(tree, hf_fcp_crn, tvb, offset+8, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(tree, hf_fcp_taskattr, tvb, offset+9, 1, ENC_BIG_ENDIAN);
    dissect_task_mgmt_flags(pinfo, tree, tvb, offset+10);
    proto_tree_add_item(tree, hf_fcp_addlcdblen, tvb, offset+11, 1, ENC_BIG_ENDIAN);
    rwflags = tvb_get_guint8(tvb, offset+11);
    if (fchdr->itlq) {
        if (rwflags & 0x02) {
            fchdr->itlq->task_flags |= SCSI_DATA_READ;
        }
        if (rwflags & 0x01) {
            fchdr->itlq->task_flags |= SCSI_DATA_WRITE;
        }
    }
    proto_tree_add_item(tree, hf_fcp_rddata, tvb, offset+11, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(tree, hf_fcp_wrdata, tvb, offset+11, 1, ENC_BIG_ENDIAN);

    tvb_len = tvb_length_remaining(tvb, offset+12);
    if (tvb_len > (16 + add_len))
      tvb_len = 16 + add_len;
    tvb_rlen = tvb_reported_length_remaining(tvb, offset+12);
    if (tvb_rlen > (16 + add_len))
      tvb_rlen = 16 + add_len;
    cdb_tvb = tvb_new_subset(tvb, offset+12, tvb_len, tvb_rlen);
    dissect_scsi_cdb(cdb_tvb, pinfo, parent_tree, SCSI_DEV_UNKNOWN, fchdr->itlq, request_data->itl);

    proto_tree_add_item(tree, hf_fcp_dl, tvb, offset+12+16+add_len,
                        4, ENC_BIG_ENDIAN);
    if (fchdr->itlq) {
        fchdr->itlq->data_length = tvb_get_ntohl(tvb, offset+12+16+add_len);
    }

    if ( ((rwflags & 0x03) == 0x03)
    &&  tvb_length_remaining(tvb, offset+12+16+add_len+4) >= 4) {
        proto_tree_add_item(tree, hf_fcp_bidir_dl, tvb, offset+12+16+add_len+4,
                            4, ENC_BIG_ENDIAN);
        if (fchdr->itlq) {
            fchdr->itlq->bidir_data_length = tvb_get_ntohl(tvb, offset+12+16+add_len+4);
        }

    }

}
Beispiel #24
0
static void dissect_tns_data(tvbuff_t *tvb, int offset, packet_info *pinfo,
	proto_tree *tree, proto_tree *tns_tree)
{
	proto_tree *data_tree = NULL, *ti;
	proto_item *hidden_item;
	int is_sns = 0;

	if ( tvb_bytes_exist(tvb, offset+2, 4) )
	{
		if ( tvb_get_guint8(tvb, offset+2) == 0xDE &&
		     tvb_get_guint8(tvb, offset+3) == 0xAD &&
		     tvb_get_guint8(tvb, offset+4) == 0xBE &&
		     tvb_get_guint8(tvb, offset+5) == 0xEF )
		{
			is_sns = 1;
		}
	}

	if ( tree )
	{
		if ( is_sns )
		{
			data_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
			    ett_tns_data, NULL, "Secure Network Services");
		}
		else
		{
			data_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
			    ett_tns_data, NULL, "Data");
		}

		hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_data, tvb, 0, 0,
					TRUE);
		PROTO_ITEM_SET_HIDDEN(hidden_item);
	}

	if ( tree )
	{
		proto_tree *df_tree = NULL;

		ti = proto_tree_add_item(data_tree, hf_tns_data_flag, tvb, offset, 2, ENC_BIG_ENDIAN);

		df_tree = proto_item_add_subtree(ti, ett_tns_data_flag);
		proto_tree_add_item(df_tree, hf_tns_data_flag_send, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_rc, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_c, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_more, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_eof, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_dic, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_rts, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(df_tree, hf_tns_data_flag_sntt, tvb, offset, 2, ENC_BIG_ENDIAN);
	}
	offset += 2;

	if ( is_sns )
	{
		col_append_str(pinfo->cinfo, COL_INFO, ", SNS");
	}
	else
	{
		col_append_str(pinfo->cinfo, COL_INFO, ", Data");
	}

	call_dissector(data_handle,
		    tvb_new_subset_remaining(tvb, offset), pinfo, data_tree);

	return;
}
Beispiel #25
0
static void
dissect(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, guint32 ip_proto)
{
  proto_tree *udp_tree = NULL;
  proto_item *ti, *hidden_item, *port_item;
  guint      len;
  guint      reported_len;
  vec_t      cksum_vec[4];
  guint32    phdr[2];
  guint16    computed_cksum;
  int        offset = 0;
  e_udphdr *udph;
  proto_tree *checksum_tree;
  proto_item *item;
  conversation_t *conv = NULL;
  struct udp_analysis *udpd = NULL;
  proto_tree *process_tree;

  udph=ep_new(e_udphdr);
  SET_ADDRESS(&udph->ip_src, pinfo->src.type, pinfo->src.len, pinfo->src.data);
  SET_ADDRESS(&udph->ip_dst, pinfo->dst.type, pinfo->dst.len, pinfo->dst.data);

  col_set_str(pinfo->cinfo, COL_PROTOCOL, (ip_proto == IP_PROTO_UDP) ? "UDP" : "UDPlite");
  col_clear(pinfo->cinfo, COL_INFO);

  udph->uh_sport=tvb_get_ntohs(tvb, offset);
  udph->uh_dport=tvb_get_ntohs(tvb, offset+2);

  col_add_fstr(pinfo->cinfo, COL_INFO, "Source port: %s  Destination port: %s",
    get_udp_port(udph->uh_sport), get_udp_port(udph->uh_dport));

  if (tree) {
    if (udp_summary_in_tree) {
      if (ip_proto == IP_PROTO_UDP) {
        ti = proto_tree_add_protocol_format(tree, proto_udp, tvb, offset, 8,
        "User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
        get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport);
      } else {
        ti = proto_tree_add_protocol_format(tree, proto_udplite, tvb, offset, 8,
        "Lightweight User Datagram Protocol, Src Port: %s (%u), Dst Port: %s (%u)",
        get_udp_port(udph->uh_sport), udph->uh_sport, get_udp_port(udph->uh_dport), udph->uh_dport);
      }
    } else {
      ti = proto_tree_add_item(tree, (ip_proto == IP_PROTO_UDP) ? proto_udp : proto_udplite, tvb, offset, 8, ENC_NA);
    }
    udp_tree = proto_item_add_subtree(ti, ett_udp);

    port_item = proto_tree_add_uint_format(udp_tree, hf_udp_srcport, tvb, offset, 2, udph->uh_sport,
	"Source port: %s (%u)", get_udp_port(udph->uh_sport), udph->uh_sport);
    /* The beginning port number, 32768 + 666 (33434), is from LBL's traceroute.c source code and this code
     * further assumes that 3 attempts are made per hop */
    if(udph->uh_sport > 32768 + 666 && udph->uh_sport <= 32768 + 666 + 30)
	    expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u",
				   ((udph->uh_sport - 32768 - 666 - 1) / 3) + 1,
				   ((udph->uh_sport - 32768 - 666 - 1) % 3) + 1
				   );

    port_item = proto_tree_add_uint_format(udp_tree, hf_udp_dstport, tvb, offset + 2, 2, udph->uh_dport,
	"Destination port: %s (%u)", get_udp_port(udph->uh_dport), udph->uh_dport);
    if(udph->uh_dport > 32768 + 666 && udph->uh_dport <= 32768 + 666 + 30)
	    expert_add_info_format(pinfo, port_item, PI_SEQUENCE, PI_CHAT, "Possible traceroute: hop #%u, attempt #%u",
				   ((udph->uh_dport - 32768 - 666 - 1) / 3) + 1,
				   ((udph->uh_dport - 32768 - 666 - 1) % 3) + 1
				   );

    hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset, 2, udph->uh_sport);
    PROTO_ITEM_SET_HIDDEN(hidden_item);
    hidden_item = proto_tree_add_uint(udp_tree, hf_udp_port, tvb, offset+2, 2, udph->uh_dport);
    PROTO_ITEM_SET_HIDDEN(hidden_item);
  }

  if (ip_proto == IP_PROTO_UDP) {
    udph->uh_ulen = udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4);
    if (udph->uh_ulen < 8) {
      /* Bogus length - it includes the header, so it must be >= 8. */
      /* XXX - should handle IPv6 UDP jumbograms (RFC 2675), where the length is zero */
      item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2,
          udph->uh_ulen, "Length: %u (bogus, must be >= 8)", udph->uh_ulen);
      expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u < 8", udph->uh_ulen);
      col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u < 8]", udph->uh_ulen);
      return;
    }
    if ((udph->uh_ulen > tvb_reported_length(tvb)) && ! pinfo->fragmented && ! pinfo->flags.in_error_pkt) {
      /* Bogus length - it goes past the end of the IP payload */
      item = proto_tree_add_uint_format(udp_tree, hf_udp_length, tvb, offset + 4, 2,
          udph->uh_ulen, "Length: %u (bogus, payload length %u)", udph->uh_ulen, tvb_reported_length(tvb));
      expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad length value %u > IP payload length", udph->uh_ulen);
      col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD UDP LENGTH %u > IP PAYLOAD LENGTH]", udph->uh_ulen);
    } else {
      if (tree) {
        proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 2, udph->uh_ulen);
        /* XXX - why is this here, given that this is UDP, not Lightweight UDP? */
        hidden_item = proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4,
                                          0, udph->uh_sum_cov);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
      }
    }
  } else {
    udph->uh_ulen = pinfo->iplen - pinfo->iphdrlen;
    udph->uh_sum_cov = tvb_get_ntohs(tvb, offset+4);
    if (((udph->uh_sum_cov > 0) && (udph->uh_sum_cov < 8)) || (udph->uh_sum_cov > udph->uh_ulen)) {
      /* Bogus length - it includes the header, so it must be >= 8, and no larger then the IP payload size. */
      if (tree) {
        hidden_item = proto_tree_add_boolean(udp_tree, hf_udplite_checksum_coverage_bad, tvb, offset + 4, 2, TRUE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
        hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
      }
      item = proto_tree_add_uint_format(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2,
          udph->uh_sum_cov, "Checksum coverage: %u (bogus, must be >= 8 and <= %u (ip.len-ip.hdr_len))",
          udph->uh_sum_cov, udph->uh_ulen);
      expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Bad checksum coverage length value %u < 8 or > %u",
                             udph->uh_sum_cov, udph->uh_ulen);
      col_append_fstr(pinfo->cinfo, COL_INFO, " [BAD LIGHTWEIGHT UDP CHECKSUM COVERAGE LENGTH %u < 8 or > %u]",
                        udph->uh_sum_cov, udph->uh_ulen);
      if (!udplite_ignore_checksum_coverage)
        return;
    } else {
      if (tree) {
        hidden_item = proto_tree_add_uint(udp_tree, hf_udp_length, tvb, offset + 4, 0, udph->uh_ulen);
        PROTO_ITEM_SET_HIDDEN(hidden_item);
        proto_tree_add_uint(udp_tree, hf_udplite_checksum_coverage, tvb, offset + 4, 2, udph->uh_sum_cov);
      }
    }
  }

  udph->uh_sum_cov = (udph->uh_sum_cov) ? udph->uh_sum_cov : udph->uh_ulen;
  udph->uh_sum = tvb_get_ntohs(tvb, offset+6);
  reported_len = tvb_reported_length(tvb);
  len = tvb_length(tvb);
  if (udph->uh_sum == 0) {
    /* No checksum supplied in the packet. */
    if ((ip_proto == IP_PROTO_UDP) && (pinfo->src.type == AT_IPv4)) {
      item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0,
        "Checksum: 0x%04x (none)", 0);

      checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
    } else {
      item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb, offset + 6, 2, 0,
        "Checksum: 0x%04x (Illegal)", 0);
      expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Illegal Checksum value (0)");
      col_append_fstr(pinfo->cinfo, COL_INFO, " [ILLEGAL CHECKSUM (0)]");

      checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                             offset + 6, 2, TRUE);
      PROTO_ITEM_SET_GENERATED(item);
    }
  } else if (!pinfo->fragmented && len >= reported_len &&
             len >= udph->uh_sum_cov && reported_len >= udph->uh_sum_cov &&
             udph->uh_sum_cov >=8) {
    /* The packet isn't part of a fragmented datagram and isn't
       truncated, so we can checksum it.
       XXX - make a bigger scatter-gather list once we do fragment
       reassembly? */

    if (((ip_proto == IP_PROTO_UDP) && (udp_check_checksum)) ||
        ((ip_proto == IP_PROTO_UDPLITE) && (udplite_check_checksum))) {
      /* Set up the fields of the pseudo-header. */
      cksum_vec[0].ptr = (const guint8 *)pinfo->src.data;
      cksum_vec[0].len = pinfo->src.len;
      cksum_vec[1].ptr = (const guint8 *)pinfo->dst.data;
      cksum_vec[1].len = pinfo->dst.len;
      cksum_vec[2].ptr = (const guint8 *)&phdr;
      switch (pinfo->src.type) {

      case AT_IPv4:
        if (ip_proto == IP_PROTO_UDP)
          phdr[0] = g_htonl((ip_proto<<16) | udph->uh_ulen);
	else
          phdr[0] = g_htonl((ip_proto<<16) | reported_len);
        cksum_vec[2].len = 4;
        break;

      case AT_IPv6:
        if (ip_proto == IP_PROTO_UDP)
          phdr[0] = g_htonl(udph->uh_ulen);
	else
          phdr[0] = g_htonl(reported_len);
        phdr[1] = g_htonl(ip_proto);
        cksum_vec[2].len = 8;
        break;

      default:
        /* UDP runs only atop IPv4 and IPv6.... */
        DISSECTOR_ASSERT_NOT_REACHED();
        break;
      }
      cksum_vec[3].ptr = tvb_get_ptr(tvb, offset, udph->uh_sum_cov);
      cksum_vec[3].len = udph->uh_sum_cov;
      computed_cksum = in_cksum(&cksum_vec[0], 4);
      if (computed_cksum == 0) {
        item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
          offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [correct]", udph->uh_sum);

        checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
        item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                                      offset + 6, 2, TRUE);
        PROTO_ITEM_SET_GENERATED(item);
        item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                                      offset + 6, 2, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
      } else {
        item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
                                          offset + 6, 2, udph->uh_sum,
          "Checksum: 0x%04x [incorrect, should be 0x%04x (maybe caused by \"UDP checksum offload\"?)]", udph->uh_sum,
          in_cksum_shouldbe(udph->uh_sum, computed_cksum));

        checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
        item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                                      offset + 6, 2, FALSE);
        PROTO_ITEM_SET_GENERATED(item);
        item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                                      offset + 6, 2, TRUE);
        PROTO_ITEM_SET_GENERATED(item);
        expert_add_info_format(pinfo, item, PI_CHECKSUM, PI_ERROR, "Bad checksum");

        col_append_fstr(pinfo->cinfo, COL_INFO, " [UDP CHECKSUM INCORRECT]");
      }
    } else {
      item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
        offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [validation disabled]", udph->uh_sum);
      checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
      item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                             offset + 6, 2, FALSE);
      PROTO_ITEM_SET_GENERATED(item);
    }
  } else {
    item = proto_tree_add_uint_format(udp_tree, hf_udp_checksum, tvb,
      offset + 6, 2, udph->uh_sum, "Checksum: 0x%04x [unchecked, not all data available]", udph->uh_sum);

    checksum_tree = proto_item_add_subtree(item, ett_udp_checksum);
    item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_good, tvb,
                             offset + 6, 2, FALSE);
    PROTO_ITEM_SET_GENERATED(item);
    item = proto_tree_add_boolean(checksum_tree, hf_udp_checksum_bad, tvb,
                             offset + 6, 2, FALSE);
    PROTO_ITEM_SET_GENERATED(item);
  }

  /* Skip over header */
  offset += 8;

  pinfo->ptype = PT_UDP;
  pinfo->srcport = udph->uh_sport;
  pinfo->destport = udph->uh_dport;

  tap_queue_packet(udp_tap, pinfo, udph);

  /* find(or create if needed) the conversation for this udp session */
  if (udp_process_info) {
    conv=find_or_create_conversation(pinfo);
    udpd=get_udp_conversation_data(conv,pinfo);
  }

  if (udpd && ((udpd->fwd && udpd->fwd->command) || (udpd->rev && udpd->rev->command))) {
    ti = proto_tree_add_text(udp_tree, tvb, offset, 0, "Process Information");
	PROTO_ITEM_SET_GENERATED(ti);
    process_tree = proto_item_add_subtree(ti, ett_udp_process_info);
	if (udpd->fwd && udpd->fwd->command) {
      proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_uid, tvb, 0, 0,
              udpd->fwd->process_uid, "%u", udpd->fwd->process_uid);
      proto_tree_add_uint_format_value(process_tree, hf_udp_proc_dst_pid, tvb, 0, 0,
              udpd->fwd->process_pid, "%u", udpd->fwd->process_pid);
      proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_uname, tvb, 0, 0,
              udpd->fwd->username, "%s", udpd->fwd->username);
      proto_tree_add_string_format_value(process_tree, hf_udp_proc_dst_cmd, tvb, 0, 0,
              udpd->fwd->command, "%s", udpd->fwd->command);
    }
    if (udpd->rev->command) {
      proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_uid, tvb, 0, 0,
              udpd->rev->process_uid, "%u", udpd->rev->process_uid);
      proto_tree_add_uint_format_value(process_tree, hf_udp_proc_src_pid, tvb, 0, 0,
              udpd->rev->process_pid, "%u", udpd->rev->process_pid);
      proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_uname, tvb, 0, 0,
              udpd->rev->username, "%s", udpd->rev->username);
      proto_tree_add_string_format_value(process_tree, hf_udp_proc_src_cmd, tvb, 0, 0,
              udpd->rev->command, "%s", udpd->rev->command);
    }
  }

  /*
   * Call sub-dissectors.
   *
   * XXX - should we do this if this is included in an error packet?
   * It might be nice to see the details of the packet that caused the
   * ICMP error, but it might not be nice to have the dissector update
   * state based on it.
   * Also, we probably don't want to run UDP taps on those packets.
   *
   * We definitely don't want to do it for an error packet if there's
   * nothing left in the packet.
   */
  if (!pinfo->flags.in_error_pkt || tvb_length_remaining(tvb, offset) > 0)
    decode_udp_ports(tvb, offset, pinfo, tree, udph->uh_sport, udph->uh_dport,
                     udph->uh_ulen);
}
Beispiel #26
0
static void dissect_tns_connect(tvbuff_t *tvb, int offset, packet_info *pinfo,
	proto_tree *tree, proto_tree *tns_tree)
{
	proto_tree *connect_tree = NULL, *ti;
	proto_item *hidden_item;
	int cd_offset;
	int cd_len;
	int tns_offset = offset-8;

	if ( tree )
	{
		connect_tree = proto_tree_add_subtree(tns_tree, tvb, offset, -1,
		    ett_tns_connect, NULL, "Connect");

		hidden_item = proto_tree_add_boolean(tns_tree, hf_tns_connect, tvb,
				    0, 0, TRUE);
		PROTO_ITEM_SET_HIDDEN(hidden_item);
	}

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

	if ( connect_tree )
	{
		proto_tree_add_item(connect_tree, hf_tns_version, tvb,
			offset, 2, ENC_BIG_ENDIAN);
	}
	offset += 2;

	if ( connect_tree )
	{
		proto_tree_add_item(connect_tree, hf_tns_compat_version, tvb,
			offset, 2, ENC_BIG_ENDIAN);
	}
	offset += 2;

	if ( connect_tree )
	{
		proto_tree *sopt_tree = NULL;

		ti = proto_tree_add_item(connect_tree, hf_tns_service_options, tvb,
			offset, 2, ENC_BIG_ENDIAN);

		sopt_tree = proto_item_add_subtree(ti, ett_tns_sopt_flag);

		dissect_tns_service_options(tvb, offset, sopt_tree);


	}
	offset += 2;

	if ( connect_tree )
	{
		proto_tree_add_item(connect_tree, hf_tns_sdu_size, tvb,
			offset, 2, ENC_BIG_ENDIAN);
	}
	offset += 2;

	if ( connect_tree )
	{
		proto_tree_add_item(connect_tree, hf_tns_max_tdu_size, tvb,
			offset, 2, ENC_BIG_ENDIAN);
	}
	offset += 2;

	if ( connect_tree )
	{
		proto_tree *ntp_tree = NULL;

		ti = proto_tree_add_item(connect_tree, hf_tns_nt_proto_characteristics, tvb,
			offset, 2, ENC_BIG_ENDIAN);

		ntp_tree = proto_item_add_subtree(ti, ett_tns_ntp_flag);

		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_hangon, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_crel, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_tduio, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_srun, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_dtest, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_cbio, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_asio, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_pio, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_grant, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_handoff, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_sigio, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_sigpipe, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_sigurg, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_urgentio, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_fdio, tvb, offset, 2, ENC_BIG_ENDIAN);
		proto_tree_add_item(ntp_tree, hf_tns_ntp_flag_testop, tvb, offset, 2, ENC_BIG_ENDIAN);
	}
	offset += 2;

	if ( connect_tree )
	{
		proto_tree_add_item(connect_tree, hf_tns_line_turnaround, tvb,
			offset, 2, ENC_BIG_ENDIAN);
	}
	offset += 2;

	if ( connect_tree )
	{
		proto_tree_add_item(connect_tree, hf_tns_value_of_one, tvb,
			offset, 2, ENC_NA);
	}
	offset += 2;

	cd_len = tvb_get_ntohs(tvb, offset);
	if ( connect_tree )
	{
		proto_tree_add_uint(connect_tree, hf_tns_connect_data_length, tvb,
			offset, 2, cd_len);
	}
	offset += 2;

	cd_offset = tvb_get_ntohs(tvb, offset);
	if ( connect_tree )
	{
		proto_tree_add_uint(connect_tree, hf_tns_connect_data_offset, tvb,
			offset, 2, cd_offset);
	}
	offset += 2;

	if ( connect_tree )
	{
		proto_tree_add_item(connect_tree, hf_tns_connect_data_max, tvb,
			offset, 4, ENC_BIG_ENDIAN);
	}
	offset += 4;

	if ( connect_tree )
	{
		proto_tree *cflag_tree = NULL;

		ti = proto_tree_add_item(connect_tree, hf_tns_connect_flags0, tvb,
			offset, 1, ENC_BIG_ENDIAN);

		cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag);

		dissect_tns_connect_flag(tvb, offset, cflag_tree);
	}
	offset += 1;

	if ( connect_tree )
	{
		proto_tree *cflag_tree = NULL;

		ti = proto_tree_add_item(connect_tree, hf_tns_connect_flags1, tvb,
			offset, 1, ENC_BIG_ENDIAN);

		cflag_tree = proto_item_add_subtree(ti, ett_tns_conn_flag);

		dissect_tns_connect_flag(tvb, offset, cflag_tree);
	}
	offset += 1;

	/*
	 * XXX - sometimes it appears that this stuff isn't present
	 * in the packet.
	 */
	if (offset + 16 <= tns_offset+cd_offset)
	{
		if ( connect_tree )
		{
			proto_tree_add_item(connect_tree, hf_tns_trace_cf1, tvb,
				offset, 4, ENC_BIG_ENDIAN);
		}
		offset += 4;

		if ( connect_tree )
		{
			proto_tree_add_item(connect_tree, hf_tns_trace_cf2, tvb,
				offset, 4, ENC_BIG_ENDIAN);
		}
		offset += 4;

		if ( connect_tree )
		{
			proto_tree_add_item(connect_tree, hf_tns_trace_cid, tvb,
				offset, 8, ENC_BIG_ENDIAN);
		}
		/* offset += 8;*/
	}

	if ( connect_tree && cd_len > 0)
	{
		proto_tree_add_item(connect_tree, hf_tns_connect_data, tvb,
			tns_offset+cd_offset, -1, ENC_ASCII|ENC_NA);
	}
	return;
}
Beispiel #27
0
static void
dissect_imap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  gboolean        is_request;
  proto_tree      *imap_tree, *reqresp_tree;
  proto_item      *ti, *hidden_item;
  gint            offset = 0;
  gint            uid_offset = 0;
  gint            folder_offset = 0;
  const guchar    *line;
  const guchar    *uid_line;
  const guchar    *folder_line;
  gint            next_offset;
  int             linelen;
  int             tokenlen;
  int             uid_tokenlen;
  int             folder_tokenlen;
  const guchar    *next_token;
  const guchar    *uid_next_token;
  const guchar    *folder_next_token;
  guchar          *tokenbuf;
  guchar          *command_token;
  int             iter;
  int             commandlen;

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


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

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

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

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

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

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

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

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

      reqresp_tree = proto_item_add_subtree(ti, ett_imap_reqresp);

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

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

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

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

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

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

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

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

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

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

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

        }

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

      }

      offset = next_offset; /* Skip over last line and \r\n at the end of it */
    }
  }
}
Beispiel #28
0
static void
expert_set_info_vformat(packet_info *pinfo, proto_item *pi, int group, int severity, int hf_index, gboolean use_vaformat,
			const char *format, va_list ap)
{
	char           formatted[ITEM_LABEL_LENGTH];
	int            tap;
	expert_info_t *ei;
	proto_tree    *tree;
	proto_item    *ti;

	if (pinfo == NULL && pi && pi->tree_data) {
		pinfo = PTREE_DATA(pi)->pinfo;
	}

	/* if this packet isn't loaded because of a read filter, don't output anything */
	if (pinfo == NULL || pinfo->num == 0) {
		return;
	}

	if (severity > highest_severity) {
		highest_severity = severity;
	}

	/* XXX: can we get rid of these checks and make them programming errors instead now? */
	if (pi != NULL && PITEM_FINFO(pi) != NULL) {
		expert_set_item_flags(pi, group, severity);
	}

	if ((pi == NULL) || (PITEM_FINFO(pi) == NULL) ||
		((guint)severity >= FI_GET_FLAG(PITEM_FINFO(pi), PI_SEVERITY_MASK))) {
		col_add_str(pinfo->cinfo, COL_EXPERT, val_to_str(severity, expert_severity_vals, "Unknown (%u)"));
	}

	if (use_vaformat) {
		g_vsnprintf(formatted, ITEM_LABEL_LENGTH, format, ap);
	} else {
		g_strlcpy(formatted, format, ITEM_LABEL_LENGTH);
	}

	tree = expert_create_tree(pi, group, severity, formatted);

	if (hf_index == -1) {
		/* If no filterable expert info, just add the message */
		ti = proto_tree_add_string(tree, hf_expert_msg, NULL, 0, 0, formatted);
		PROTO_ITEM_SET_GENERATED(ti);
	} else {
		/* If filterable expert info, hide the "generic" form of the message,
		   and generate the formatted filterable expert info */
		ti = proto_tree_add_none_format(tree, hf_index, NULL, 0, 0, "%s", formatted);
		PROTO_ITEM_SET_GENERATED(ti);
		ti = proto_tree_add_string(tree, hf_expert_msg, NULL, 0, 0, formatted);
		PROTO_ITEM_SET_HIDDEN(ti);
	}

	ti = proto_tree_add_uint_format_value(tree, hf_expert_severity, NULL, 0, 0, severity,
					      "%s", val_to_str_const(severity, expert_severity_vals, "Unknown"));
	PROTO_ITEM_SET_GENERATED(ti);
	ti = proto_tree_add_uint_format_value(tree, hf_expert_group, NULL, 0, 0, group,
					      "%s", val_to_str_const(group, expert_group_vals, "Unknown"));
	PROTO_ITEM_SET_GENERATED(ti);

	tap = have_tap_listener(expert_tap);

	if (!tap)
		return;

	ei = wmem_new(wmem_packet_scope(), expert_info_t);

	ei->packet_num  = pinfo->num;
	ei->group       = group;
	ei->severity    = severity;
	ei->hf_index    = hf_index;
	ei->protocol    = pinfo->current_proto;
	ei->summary     = wmem_strdup(wmem_packet_scope(), formatted);

	/* if we have a proto_item (not a faked item), set expert attributes to it */
	if (pi != NULL && PITEM_FINFO(pi) != NULL) {
		ei->pitem = pi;
	}
	/* XXX: remove this because we don't have an internal-only function now? */
	else {
		ei->pitem = NULL;
	}

	tap_queue_packet(expert_tap, pinfo, ei);
}
Beispiel #29
0
static void
dissect_ascend(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_tree			*fh_tree;
  proto_item			*ti, *hidden_item;
  union wtap_pseudo_header	*pseudo_header = pinfo->pseudo_header;

  /* load the top pane info. This should be overwritten by
     the next protocol in the stack */
  col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "N/A");
  col_set_str(pinfo->cinfo, COL_RES_DL_DST, "N/A");
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "N/A");
  col_set_str(pinfo->cinfo, COL_INFO, "Lucent/Ascend packet trace");

  /* If this is a transmitted or received PPP frame, set the PPP direction. */
  switch (pseudo_header->ascend.type) {

  case ASCEND_PFX_WDS_X:
    pinfo->p2p_dir = P2P_DIR_SENT;
    break;

  case ASCEND_PFX_WDS_R:
    pinfo->p2p_dir = P2P_DIR_RECV;
    break;
  }

  /* populate a tree in the second pane with the status of the link
     layer (ie none) */
  if(tree) {
    ti = proto_tree_add_protocol_format(tree, proto_ascend, tvb, 0, 0,
					"Lucent/Ascend packet trace");
    fh_tree = proto_item_add_subtree(ti, ett_raw);
    proto_tree_add_uint(fh_tree, hf_link_type, tvb, 0, 0,
			pseudo_header->ascend.type);
    if (pseudo_header->ascend.type == ASCEND_PFX_WDD) {
      proto_tree_add_string(fh_tree, hf_called_number, tvb, 0, 0,
			  pseudo_header->ascend.call_num);
      proto_tree_add_uint(fh_tree, hf_chunk, tvb, 0, 0,
			  pseudo_header->ascend.chunk);
      hidden_item = proto_tree_add_uint(fh_tree, hf_session_id, tvb, 0, 0, 0);
	  PROTO_ITEM_SET_HIDDEN(hidden_item);
    } else {  /* It's wandsession data */
      proto_tree_add_string(fh_tree, hf_user_name, tvb, 0, 0,
			  pseudo_header->ascend.user);
      proto_tree_add_uint(fh_tree, hf_session_id, tvb, 0, 0,
			  pseudo_header->ascend.sess);
      hidden_item = proto_tree_add_uint(fh_tree, hf_chunk, tvb, 0, 0, 0);
	  PROTO_ITEM_SET_HIDDEN(hidden_item);
    }
    proto_tree_add_uint(fh_tree, hf_task, tvb, 0, 0, pseudo_header->ascend.task);
  }

  switch (pseudo_header->ascend.type) {
    case ASCEND_PFX_WDS_X:
    case ASCEND_PFX_WDS_R:
      call_dissector(ppp_hdlc_handle, tvb, pinfo, tree);
      break;
    case ASCEND_PFX_WDD:
      call_dissector(eth_withoutfcs_handle, tvb, pinfo, tree);
      break;
    default:
      break;
  }
}
Beispiel #30
0
static int
dissect_websocket_payload(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, proto_tree *ws_tree, guint8 opcode, guint payload_length, guint8 mask, const guint8* masking_key)
{
  guint offset = 0;
  proto_item *ti_unmask, *ti;
  dissector_handle_t handle;
  proto_tree *pl_tree, *mask_tree = NULL;
  tvbuff_t *payload_tvb = NULL;

  /* Payload */
  ti = proto_tree_add_item(ws_tree, hf_ws_payload, tvb, offset, payload_length, ENC_NA);
  pl_tree = proto_item_add_subtree(ti, ett_ws_pl);
  if(mask){
    payload_tvb = tvb_unmasked(tvb, offset, payload_length, masking_key);
    tvb_set_child_real_data_tvbuff(tvb, payload_tvb);
    add_new_data_source(pinfo, payload_tvb, payload_length > tvb_length(payload_tvb) ? "Unmasked Data (truncated)" : "Unmasked Data");
    ti = proto_tree_add_item(ws_tree, hf_ws_payload_unmask, payload_tvb, offset, payload_length, ENC_NA);
    mask_tree = proto_item_add_subtree(ti, ett_ws_mask);
  }else{
    payload_tvb = tvb_new_subset(tvb, offset, payload_length, -1);
  }

  handle = dissector_get_uint_handle(port_subdissector_table, pinfo->match_uint);
  if(handle != NULL){
    call_dissector_only(handle, payload_tvb, pinfo, tree, NULL);
  }else{
    dissector_try_heuristic(heur_subdissector_list, payload_tvb, pinfo, tree, NULL);
  }

  /* Extension Data */
  /* TODO: Add dissector of Extension (not extension available for the moment...) */

  /* Application Data */
  switch(opcode){

    case WS_CONTINUE: /* Continue */
      proto_tree_add_item(pl_tree, hf_ws_payload_continue, tvb, offset, payload_length, ENC_NA);
      /* TODO: Add Fragmentation support... */
    break;

    case WS_TEXT: /* Text */
    if(mask){

      proto_tree_add_item(pl_tree, hf_ws_payload_text_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text_unmask, payload_tvb, offset, payload_length, ENC_UTF_8|ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_text, payload_tvb, offset, payload_length, ENC_UTF_8|ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      const gchar  *saved_match_string = pinfo->match_string;
      void *save_private_data = pinfo->private_data;

      pinfo->match_string = NULL;
      pinfo->private_data = NULL;
      switch(pref_text_type){
      case WEBSOCKET_TEXT:
          call_dissector(text_lines_handle, payload_tvb, pinfo, pl_tree);
          break;
      case WEBSOCKET_JSON:
          call_dissector(json_handle, payload_tvb, pinfo, pl_tree);
          break;
      case WEBSOCKET_NONE:
          /* falltrough */
      default:
          proto_tree_add_item(pl_tree, hf_ws_payload_text, tvb, offset, payload_length, ENC_UTF_8|ENC_NA);
          break;
      }
      pinfo->match_string = saved_match_string;
      pinfo->private_data = save_private_data;
    }
    offset += payload_length;
    break;

    case WS_BINARY: /* Binary */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_binary_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary_unmask, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_binary, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_binary, tvb, offset, payload_length, ENC_NA);
    }
    offset += payload_length;
    break;

    case WS_CLOSE: /* Close */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_close_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_unmask, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_status_code, payload_tvb, offset, 2, ENC_BIG_ENDIAN);
      PROTO_ITEM_SET_GENERATED(ti_unmask);

      if(payload_length > 2){
        ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_close_reason, payload_tvb, offset+2, payload_length-2, ENC_ASCII|ENC_NA);
        PROTO_ITEM_SET_GENERATED(ti_unmask);
      }
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_close, tvb, offset, payload_length, ENC_NA);
      proto_tree_add_item(pl_tree, hf_ws_payload_close_status_code, tvb, offset, 2, ENC_BIG_ENDIAN);
      if(payload_length > 2){
        proto_tree_add_item(pl_tree, hf_ws_payload_close_reason, tvb, offset+2, payload_length-2, ENC_ASCII|ENC_NA);
      }
    }
    offset += payload_length;
    break;

    case WS_PING: /* Ping */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_ping_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping_unmask, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_ping, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_ping, tvb, offset, payload_length, ENC_NA);
    }
    offset += payload_length;
    break;

    case WS_PONG: /* Pong */
    if(mask){
      proto_tree_add_item(pl_tree, hf_ws_payload_pong_mask, tvb, offset, payload_length, ENC_NA);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong_unmask, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_GENERATED(ti_unmask);
      ti_unmask = proto_tree_add_item(mask_tree, hf_ws_payload_pong, payload_tvb, offset, payload_length, ENC_NA);
      PROTO_ITEM_SET_HIDDEN(ti_unmask);
    }else{
      proto_tree_add_item(pl_tree, hf_ws_payload_pong, tvb, offset, payload_length, ENC_NA);
    }
    offset += payload_length;
    break;

    default: /* Unknown */
      ti = proto_tree_add_item(pl_tree, hf_ws_payload_unknown, tvb, offset, payload_length, ENC_NA);
      expert_add_info_format(pinfo, ti, &ei_ws_payload_unknown, "Dissector for Websocket Opcode (%d)"
        " code not implemented, Contact Wireshark developers"
        " if you want this supported", opcode);
    break;
  }
  return offset;
}