Exemplo n.º 1
0
static gboolean
dissect_fcip (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
              gboolean check_port)
{
    gint offset = 0,
         start  = 0,
         frame_len = 0;
    gint bytes_remaining = tvb_captured_length (tvb);
    guint8 pflags, sof = 0, eof = 0;
   /* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti;
    proto_tree *fcip_tree = NULL;
    tvbuff_t *next_tvb;
    fc_data_t fc_data;

    if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) {
        return FALSE;
    }

    if (check_port &&
        ((pinfo->srcport != fcip_port) && (pinfo->destport != fcip_port))) {
        return FALSE;
    }

    while (bytes_remaining > FCIP_ENCAP_HEADER_LEN) {
        if ((offset = get_next_fcip_header_offset (tvb, pinfo, offset)) == -1) {
            return FALSE;
        }
        else if (offset == -2) {
            /* We need more data to desegment */
            return (TRUE);
        }

        start = offset;
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCIP");

        frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4;

        if (bytes_remaining < frame_len) {
            if(fcip_desegment && pinfo->can_desegment) {
                /*
                 * This frame doesn't have all of the data for
                 * this message, but we can do reassembly on it.
                 *
                 * Tell the TCP dissector where the data for this
                 * message starts in the data it handed us, and
                 * how many more bytes we need, and return.
                 */
                pinfo->desegment_offset = offset;
                pinfo->desegment_len = frame_len - bytes_remaining;
                return (TRUE);
            }
        }

        pflags = tvb_get_guint8 (tvb, start+8);

        if (tree) {
            if (FCIP_IS_SF (pflags)) {
                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP");
            }
            else if (tvb_bytes_exist (tvb, offset, offset+frame_len-4)) {
                sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);
                eof = tvb_get_guint8 (tvb, offset+frame_len - 4);

                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP (%s/%s)",
                                                     val_to_str (sof, fcip_sof_vals,
                                                                 "0x%x"),
                                                     val_to_str (eof, fcip_eof_vals,
                                                                 "0x%x"));
            }
            else {
                sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);

                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP (%s/%s)",
                                                     val_to_str (sof, fcip_sof_vals,
                                                                 "0x%x"),
                                                     "NA");
            }
            fcip_tree = proto_item_add_subtree (ti, ett_fcip);
            /* Dissect the Common FC Encap header */
            dissect_fcencap_header (tvb, fcip_tree, offset);

            offset += FCIP_ENCAP_HEADER_LEN;

            if (!FCIP_IS_SF (pflags)) {
                /* print SOF */
                proto_tree_add_item (fcip_tree, hf_fcip_sof, tvb, offset, 1, ENC_BIG_ENDIAN);
                proto_tree_add_item (fcip_tree, hf_fcip_sof_c, tvb, offset+2, 1, ENC_BIG_ENDIAN);
                /* print EOF */

                offset += (frame_len-FCIP_ENCAP_HEADER_LEN-4);
                if (tvb_bytes_exist (tvb, offset, 4)) {
                    proto_tree_add_item (fcip_tree, hf_fcip_eof, tvb, offset, 1, ENC_BIG_ENDIAN);
                    proto_tree_add_item (fcip_tree, hf_fcip_eof_c, tvb, offset+2, 1, ENC_BIG_ENDIAN);
                }
            }
        }

        /* Call the FC Dissector if this is carrying an FC frame */
        if (!FCIP_IS_SF(pflags)) {
            /* Set the SOF/EOF flags in the packet_info header */
            fc_data.sof_eof = 0;

            if (sof) {
                if ((sof == FCIP_SOFi3) || (sof == FCIP_SOFi2) || (sof == FCIP_SOFi4)) {
                    fc_data.sof_eof = FC_DATA_SOF_FIRST_FRAME;
                }
                else if (sof == FCIP_SOFf) {
                    fc_data.sof_eof = FC_DATA_SOF_SOFF;
                }

                if (eof != FCIP_EOFn) {
                    fc_data.sof_eof |= FC_DATA_EOF_LAST_FRAME;
                }
                else if (eof != FCIP_EOFt) {
                    fc_data.sof_eof |= FC_DATA_EOF_INVALID;
                }
            }

            /* Special frame bit is not set */
            next_tvb = tvb_new_subset_remaining (tvb, FCIP_ENCAP_HEADER_LEN+4);
            if (fc_handle) {
                fc_data.ethertype = 0;
                call_dissector_with_data(fc_handle, next_tvb, pinfo, tree, &fc_data);
            }
            else if (data_handle) {
                call_dissector (data_handle, next_tvb, pinfo, tree);
            }
        }
        else {
            col_set_str(pinfo->cinfo, COL_INFO, "Special Frame");
            if (FCIP_IS_CH (pflags)) {
                col_append_str(pinfo->cinfo, COL_INFO, "(Changed)");
            }

            dissect_fcip_sf (tvb, fcip_tree, offset+4);
        }

        bytes_remaining -= frame_len;
    }

    return (TRUE);
}
Exemplo n.º 2
0
static gboolean ros_try_string(const char *oid, tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	ros_info_t *rinfo;
	gint32     opcode_lcl = 0;
	const gchar *opname = NULL;
	const gchar *suffix = NULL;
	new_dissector_t opdissector = NULL;
	const value_string *lookup;
	proto_item *item=NULL;
	proto_tree *ros_tree=NULL;
	struct SESSION_DATA_STRUCTURE* session = NULL;

	session = ( (struct SESSION_DATA_STRUCTURE*)(pinfo->private_data) );

	if((session != NULL) && ((rinfo = (ros_info_t*)g_hash_table_lookup(protocol_table, oid)) != NULL)) {

		if(tree){
			item = proto_tree_add_item(tree, *(rinfo->proto), tvb, 0, -1, ENC_NA);
			ros_tree = proto_item_add_subtree(item, *(rinfo->ett_proto));
		}

		col_set_str(pinfo->cinfo, COL_PROTOCOL, rinfo->name);

		/* if this is a bind operation */
		if((session->ros_op & ROS_OP_TYPE_MASK) == ROS_OP_BIND) {
			/* use the in-built operation codes */
			if((session->ros_op & ROS_OP_PDU_MASK) ==  ROS_OP_ERROR)
				opcode_lcl = err_ros_bind;
			else
				opcode_lcl = op_ros_bind;
		} else
			/* otherwise just take the opcode */
			opcode_lcl = session->ros_op & ROS_OP_OPCODE_MASK;

		/* default lookup in the operations */
		lookup = rinfo->opr_code_strings;

		switch(session->ros_op & ROS_OP_PDU_MASK) {
		case ROS_OP_ARGUMENT:
			opdissector = ros_lookup_opr_dissector(opcode_lcl, rinfo->opr_code_dissectors, TRUE);
			suffix = "_argument";
			break;
		case ROS_OP_RESULT:
			opdissector = ros_lookup_opr_dissector(opcode_lcl, rinfo->opr_code_dissectors, FALSE);
			suffix = "_result";
			break;
		case ROS_OP_ERROR:
			opdissector = ros_lookup_err_dissector(opcode_lcl, rinfo->err_code_dissectors);
			lookup = rinfo->err_code_strings;
			break;
		default:
			break;
		}

		if(opdissector) {

			opname = val_to_str(opcode_lcl, lookup, "Unknown opcode (%d)");

			col_set_str(pinfo->cinfo, COL_INFO, opname);
			if(suffix)
				col_append_str(pinfo->cinfo, COL_INFO, suffix);

			(*opdissector)(tvb, pinfo, ros_tree, NULL);

			return TRUE;
		}
	}

	return FALSE;
}
Exemplo n.º 3
0
static void dissect_nv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
   proto_item *ti;
   proto_tree *nv_tree, *nv_header_tree, *nv_var_tree,*nv_varheader_tree;
   gint offset = 0;
   char szText[200];
   int nMax = sizeof(szText)-1;

   gint i;

   col_set_str(pinfo->cinfo, COL_PROTOCOL, "TC-NV");

   col_clear(pinfo->cinfo, COL_INFO);

   NvSummaryFormater(tvb, offset, szText, nMax);
   col_append_str(pinfo->cinfo, COL_INFO, szText);

   if (tree)
   {
      guint16 nv_count;

      ti = proto_tree_add_item(tree, proto_nv, tvb, 0, -1, ENC_NA);
      nv_tree = proto_item_add_subtree(ti, ett_nv);
      proto_item_append_text(ti,": %s",szText);

      ti = proto_tree_add_item(nv_tree, hf_nv_header, tvb, offset, NvParserHDR_Len, ENC_NA);

      nv_header_tree = proto_item_add_subtree(ti, ett_nv_header);

      ti= proto_tree_add_item(nv_header_tree, hf_nv_publisher, tvb, offset, sizeof(guint8)*6, ENC_NA);
      NvPublisherFormater(tvb, offset, szText, nMax);
      proto_item_set_text(ti, "%s", szText);
      offset+=(sizeof(guint8)*6);

      proto_tree_add_item(nv_header_tree, hf_nv_count, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
      nv_count = tvb_get_letohs(tvb, offset);
      offset+=sizeof(guint16);

      proto_tree_add_item(nv_header_tree, hf_nv_cycleindex, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
      offset = NvParserHDR_Len;

      for ( i=0; i < nv_count; i++ )
      {
         guint16 var_length = tvb_get_letohs(tvb, offset+4);

         ti = proto_tree_add_item(nv_tree, hf_nv_variable, tvb, offset, ETYPE_88A4_NV_DATA_HEADER_Len+var_length, ENC_NA);
         NvVarHeaderFormater(tvb, offset, szText, nMax);
         proto_item_set_text(ti, "%s", szText);

         nv_var_tree = proto_item_add_subtree(ti, ett_nv_var);
         ti = proto_tree_add_item(nv_var_tree, hf_nv_varheader, tvb, offset, ETYPE_88A4_NV_DATA_HEADER_Len, ENC_NA);

         nv_varheader_tree = proto_item_add_subtree(ti, ett_nv_varheader);
         proto_tree_add_item(nv_varheader_tree, hf_nv_id, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
         offset+=sizeof(guint16);

         proto_tree_add_item(nv_varheader_tree, hf_nv_hash, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
         offset+=sizeof(guint16);

         proto_tree_add_item(nv_varheader_tree, hf_nv_length, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
         offset+=sizeof(guint16);

         proto_tree_add_item(nv_varheader_tree, hf_nv_quality, tvb, offset, sizeof(guint16), ENC_LITTLE_ENDIAN);
         offset+=sizeof(guint16);

         proto_tree_add_item(nv_var_tree, hf_nv_data, tvb, offset, var_length, ENC_NA);
         offset+=var_length;
      }
   }
}
Exemplo n.º 4
0
int
dissect_xdlc_control(tvbuff_t *tvb, int offset, packet_info *pinfo,
  proto_tree *xdlc_tree, int hf_xdlc_control, gint ett_xdlc_control,
  const xdlc_cf_items *cf_items_nonext, const xdlc_cf_items *cf_items_ext,
  const value_string *u_modifier_short_vals_cmd,
  const value_string *u_modifier_short_vals_resp, gboolean is_response,
  gboolean is_extended, gboolean append_info)
{
    guint16 control;
    int control_len;
    const xdlc_cf_items *cf_items;
    const char *control_format;
    guint16 poll_final;
    char *info;
    proto_tree *tc, *control_tree;
    const gchar *frame_type = NULL;
    const gchar *modifier;

    info=(char *)ep_alloc(80);
    switch (tvb_get_guint8(tvb, offset) & 0x03) {

    case XDLC_S:
        /*
	 * Supervisory frame.
	 */
	if (is_extended) {
	    control = tvb_get_letohs(tvb, offset);
	    control_len = 2;
	    cf_items = cf_items_ext;
	    control_format = "Control field: %s (0x%04X)";
	} else {
	    control = tvb_get_guint8(tvb, offset);
	    control_len = 1;
	    cf_items = cf_items_nonext;
	    control_format = "Control field: %s (0x%02X)";
	}
	switch (control & XDLC_S_FTYPE_MASK) {
	case XDLC_RR:
	    frame_type = "RR";
	    break;

	case XDLC_RNR:
	    frame_type = "RNR";
	    break;

	case XDLC_REJ:
	    frame_type = "REJ";
	    break;

	case XDLC_SREJ:
	    frame_type = "SREJ";
	    break;
	}
	if (is_extended) {
	    poll_final = (control & XDLC_P_F_EXT);
	    g_snprintf(info, 80, "S%s, func=%s, N(R)=%u",
		 	(poll_final ?
		 	    (is_response ? " F" : " P") :
		 	    ""),
			frame_type,
			(control & XDLC_N_R_EXT_MASK) >> XDLC_N_R_EXT_SHIFT);
	} else {
	    poll_final = (control & XDLC_P_F);
	    g_snprintf(info, 80, "S%s, func=%s, N(R)=%u",
		 	(poll_final ?
		 	    (is_response ? " F" : " P") :
		 	    ""),
		 	frame_type,
			(control & XDLC_N_R_MASK) >> XDLC_N_R_SHIFT);
	}
	if (append_info) {
	    col_append_str(pinfo->cinfo, COL_INFO, ", ");
	    col_append_str(pinfo->cinfo, COL_INFO, info);
	} else {
	    col_add_str(pinfo->cinfo, COL_INFO, info);
	}
	if (xdlc_tree) {
	    tc = proto_tree_add_uint_format(xdlc_tree, hf_xdlc_control, tvb,
		offset, control_len, control, control_format, info, control);
	    control_tree = proto_item_add_subtree(tc, ett_xdlc_control);
	    proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_n_r,
		tvb, offset, control_len, control);
	    if (poll_final) {
		proto_tree_add_boolean(control_tree,
			(is_response ? *cf_items->hf_xdlc_f :
				       *cf_items->hf_xdlc_p),
			tvb, offset, control_len, control);
	    }
	    proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_s_ftype,
		tvb, offset, control_len, control);
	    /* This will always say it's a supervisory frame */
	    proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_ftype_s_u,
		tvb, offset, control_len, control);
	}
	break;

    case XDLC_U:
	/*
	 * Unnumbered frame.
	 *
	 * XXX - is this two octets, with a P/F bit, in HDLC extended
	 * operation?  It's one octet in LLC, even though the control
	 * field of I and S frames is a 2-byte extended-operation field
	 * in LLC.  Given that there are no sequence numbers in the
	 * control field of a U frame, there doesn't appear to be any
	 * need for it to be 2 bytes in extended operation.
	 */
	if (u_modifier_short_vals_cmd == NULL)
		u_modifier_short_vals_cmd = modifier_short_vals_cmd;
	if (u_modifier_short_vals_resp == NULL)
		u_modifier_short_vals_resp = modifier_short_vals_resp;
	control = tvb_get_guint8(tvb, offset);
	control_len = 1;
	cf_items = cf_items_nonext;
	control_format = "Control field: %s (0x%02X)";
	if (is_response) {
		modifier = val_to_str(control & XDLC_U_MODIFIER_MASK,
			u_modifier_short_vals_resp, "Unknown");
	} else {
		modifier = val_to_str(control & XDLC_U_MODIFIER_MASK,
			u_modifier_short_vals_cmd, "Unknown");
	}
	poll_final = (control & XDLC_P_F);
	g_snprintf(info, 80, "U%s, func=%s",
		(poll_final ?
		    (is_response ? " F" : " P") :
		    ""),
		modifier);
	if (append_info) {
	    col_append_str(pinfo->cinfo, COL_INFO, ", ");
    	col_append_str(pinfo->cinfo, COL_INFO, info);
	} else {
	    col_add_str(pinfo->cinfo, COL_INFO, info);
	}
	if (xdlc_tree) {
	    tc = proto_tree_add_uint_format(xdlc_tree, hf_xdlc_control,	tvb,
		offset, control_len, control, control_format, info, control);
	    control_tree = proto_item_add_subtree(tc, ett_xdlc_control);
	    if (poll_final) {
		proto_tree_add_boolean(control_tree,
			(is_response ? *cf_items->hf_xdlc_f:
				       *cf_items->hf_xdlc_p),
			tvb, offset, control_len, control);
	    }
	    proto_tree_add_uint(control_tree,
		(is_response ? *cf_items->hf_xdlc_u_modifier_resp :
			       *cf_items->hf_xdlc_u_modifier_cmd),
	    	tvb, offset, control_len, control);
	    /* This will always say it's an unnumbered frame */
	    proto_tree_add_uint(control_tree, *cf_items->hf_xdlc_ftype_s_u,
		tvb, offset, control_len, control);
	}
	break;

    default:
	/*
	 * Information frame.
	 */
	if (is_extended) {
	    control = tvb_get_letohs(tvb, offset);
	    control_len = 2;
	    cf_items = cf_items_ext;
	    control_format = "Control field: %s (0x%04X)";
	    poll_final = (control & XDLC_P_F_EXT);
	    g_snprintf(info, 80, "I%s, N(R)=%u, N(S)=%u",
			((control & XDLC_P_F_EXT) ? " P" : ""),
			(control & XDLC_N_R_EXT_MASK) >> XDLC_N_R_EXT_SHIFT,
			(control & XDLC_N_S_EXT_MASK) >> XDLC_N_S_EXT_SHIFT);
	} else {
Exemplo n.º 5
0
/* note that even if ajp13_tree is null on the first pass, we still
 * need to dissect the packet in order to determine if there is a
 * content-length, and thus if there is a subsequent automatic
 * request-body transmitted in the next request packet. if there is a
 * content-length, we record the fact in the conversation context.
 * ref the top of this file for comments explaining the multi-pass
 * thing.
*/
static void
display_req_forward(tvbuff_t *tvb, packet_info *pinfo,
                    proto_tree *ajp13_tree,
                    ajp13_conv_data* cd)
{
  int pos = 0;
  guint8 meth;
  guint8 cod;
  const gchar *ver;
  guint16 ver_len;
  const gchar *uri;
  guint16 uri_len;
  const gchar *raddr;
  guint16 raddr_len;
  const gchar *rhost;
  guint16 rhost_len;
  const gchar *srv;
  guint16 srv_len;
  guint nhdr;
  guint i;

  if (ajp13_tree)
    proto_tree_add_item(ajp13_tree, hf_ajp13_magic, tvb, pos, 2, ENC_NA);
  pos+=2;

  if (ajp13_tree)
    proto_tree_add_item(ajp13_tree, hf_ajp13_len, tvb, pos, 2, ENC_BIG_ENDIAN);
  pos+=2;

  /* PACKET CODE
   */
  cod = tvb_get_guint8(tvb, 4);
  if (ajp13_tree)
    proto_tree_add_item(ajp13_tree, hf_ajp13_code, tvb, pos, 1, ENC_BIG_ENDIAN);
  pos+=1;
  if ( cod == MTYPE_CPING ) {
    col_append_str(pinfo->cinfo, COL_INFO, "CPING" );
    return;
  }

  /* HTTP METHOD (ENCODED AS INTEGER)
   */
  meth = tvb_get_guint8(tvb, pos);
  col_append_str(pinfo->cinfo, COL_INFO, val_to_str(meth, http_method_codes, "Unknown method %u"));
  if (ajp13_tree)
    proto_tree_add_item(ajp13_tree, hf_ajp13_method, tvb, pos, 1, ENC_BIG_ENDIAN);
  pos+=1;

  /* HTTP VERSION STRING
   */
  ver = ajp13_get_nstring(tvb, pos, &ver_len);
  if (ajp13_tree)
    proto_tree_add_string(ajp13_tree, hf_ajp13_ver, tvb, pos, ver_len+2, ver);
  pos=pos+ver_len+2;  /* skip over size + chars + trailing null */

  /* URI
   */
  uri = ajp13_get_nstring(tvb, pos, &uri_len);
  if (ajp13_tree)
    proto_tree_add_string(ajp13_tree, hf_ajp13_uri, tvb, pos, uri_len+2, uri);
  pos=pos+uri_len+2;  /* skip over size + chars + trailing null */


  col_append_fstr(pinfo->cinfo, COL_INFO, " %s %s", uri, ver);


  /* REMOTE ADDRESS
   */
  raddr = ajp13_get_nstring(tvb, pos, &raddr_len);
  if (ajp13_tree)
    proto_tree_add_string(ajp13_tree, hf_ajp13_raddr, tvb, pos, raddr_len+2, raddr);
  pos=pos+raddr_len+2;  /* skip over size + chars + trailing null */

  /* REMOTE HOST
   */
  rhost = ajp13_get_nstring(tvb, pos, &rhost_len);
  if (ajp13_tree)
    proto_tree_add_string(ajp13_tree, hf_ajp13_rhost, tvb, pos, rhost_len+2, rhost);
  pos=pos+rhost_len+2;  /* skip over size + chars + trailing null */

  /* SERVER NAME
   */
  srv = ajp13_get_nstring(tvb, pos, &srv_len);
  if (ajp13_tree)
    proto_tree_add_string(ajp13_tree, hf_ajp13_srv, tvb, pos, srv_len+2, srv);
  pos=pos+srv_len+2;  /* skip over size + chars + trailing null */

  /* SERVER PORT
   */
  if (ajp13_tree)
    proto_tree_add_item(ajp13_tree, hf_ajp13_port, tvb, pos, 2, ENC_BIG_ENDIAN);
  pos+=2;

  /* IS SSL?
   */
  if (ajp13_tree)
    proto_tree_add_item(ajp13_tree, hf_ajp13_sslp, tvb, pos, 1, ENC_NA);
  pos+=1;

  /* NUM HEADERS
   */
  nhdr = tvb_get_ntohs(tvb, pos);

  if (ajp13_tree)
    proto_tree_add_item(ajp13_tree, hf_ajp13_nhdr, tvb, pos, 2, ENC_BIG_ENDIAN);
  pos+=2;
  cd->content_length = 0;

  /* HEADERS
   */
  for(i=0; i<nhdr; i++) {

    guint8 hcd;
    guint8 hid;
    const gchar* hname = NULL;
    int hpos = pos;
    int cl = 0;
    const gchar *hval;
    guint16 hval_len, hname_len;

    /* HEADER CODE/NAME
     */
    hcd = tvb_get_guint8(tvb, pos);

    if (hcd == 0xA0) {
      pos+=1;
      hid = tvb_get_guint8(tvb, pos);
      pos+=1;

      if (hid >= array_length(req_headers))
        hid = 0;

      hval = ajp13_get_nstring(tvb, pos, &hval_len);

      proto_tree_add_string_format(ajp13_tree, *req_headers[hid],
                                     tvb, hpos, 2+hval_len+2, hval,
                                     "%s", hval);
      pos+=hval_len+2;

      if (hid == 0x08)
        cl = 1;
    } else {
      hname = ajp13_get_nstring(tvb, pos, &hname_len);
      pos+=hname_len+2;

      hval = ajp13_get_nstring(tvb, pos, &hval_len);

      proto_tree_add_string_format(ajp13_tree, hf_ajp13_additional_header,
                                     tvb, hpos, hname_len+2+hval_len+2,
                                     wmem_strdup_printf(wmem_packet_scope(), "%s: %s", hname, hval),
                                     "%s: %s", hname, hval);
      pos+=hval_len+2;
    }

    if (cl) {
      cl = atoi(hval);
      cd->content_length = cl;
    }
  }

  /* ATTRIBUTES
   */
  while(tvb_reported_length_remaining(tvb, pos) > 0) {
    guint8 aid;
    const gchar* aname = NULL;
    const gchar* aval;
    guint16 aval_len, aname_len;

    int apos = pos;

    /* ATTRIBUTE CODE/NAME
     */
    aid = tvb_get_guint8(tvb, pos);
    pos+=1;

    if (aid == 0xFF) {
      /* request terminator */
      break;
    }
    if (aid == 0x0A) {
      /* req_attribute - name and value follow */

      aname = ajp13_get_nstring(tvb, pos, &aname_len);
      pos+=aname_len+2;

      aval = ajp13_get_nstring(tvb, pos, &aval_len);
      pos+=aval_len+2;

      proto_tree_add_string_format(ajp13_tree, hf_ajp13_req_attribute,
                                     tvb, apos, 1+aname_len+2+aval_len+2,
                                     wmem_strdup_printf(wmem_packet_scope(), "%s: %s", aname, aval),
                                     "%s: %s", aname, aval);
    } else if (aid == 0x0B ) {
      /* ssl_key_length */
      if (ajp13_tree) {
        proto_tree_add_uint(ajp13_tree, hf_ajp13_ssl_key_size,
                            tvb, apos, 1+2, tvb_get_ntohs(tvb, pos));
      }
      pos+=2;
    } else {

      if (aid >= array_length(req_attributes))
        aid = 0;

      aval = ajp13_get_nstring(tvb, pos, &aval_len);
      pos+=aval_len+2;

      proto_tree_add_string_format(ajp13_tree, *req_attributes[aid],
                                     tvb, apos, 1+aval_len+2, aval,
                                     "%s", aval);
    }
  }
}
Exemplo n.º 6
0
/* Decoder State Machine.  Currently only used to snoop on
   client-user-name as sent by the client up connection establishment.
*/
static void
rlogin_state_machine(rlogin_hash_entry_t *hash_info, tvbuff_t *tvb, packet_info *pinfo)
{
	guint length;
	gint stringlen;

	/* Won't change state if already seen this packet */
	if (pinfo->fd->flags.visited)
	{
		return;
	}

	/* rlogin stream decoder */
	/* Just watch for the second packet from client with the user name and */
	/* terminal type information. */

	if (pinfo->destport != RLOGIN_PORT)
	{
		return;
	}

	/* exit if already passed username in conversation */
	if (hash_info->state == DONE)
	{
		return;
	}

	/* exit if no data */
	length = tvb_length(tvb);
	if (length == 0)
	{
		return;
	}

	if (hash_info->state == NONE)
	{
		/* new connection*/
		if (tvb_get_guint8(tvb, 0) != '\0')
		{
			/* We expected a null, but didn't get one; quit. */
			hash_info->state = DONE;
			return;
		}
		else
		{
			if (length <= 1)
			{
				/* Still waiting for data */
				hash_info->state = USER_INFO_WAIT;
			}
			else
			{
				/* Have info, store frame number */
				hash_info->state = DONE;
				hash_info->info_framenum = pinfo->fd->num;
			}
		}
	}
	/* expect user data here */
	/* TODO: may need to do more checking here? */
	else
	if (hash_info->state == USER_INFO_WAIT)
	{
		/* Store frame number here */
		hash_info->state = DONE;
		hash_info->info_framenum = pinfo->fd->num;

		/* Work out length of string to copy */
		stringlen = tvb_strnlen(tvb, 0, NAME_LEN);
		if (stringlen == -1)
			stringlen = NAME_LEN - 1;   /* no '\0' found */
		else if (stringlen > NAME_LEN - 1)
			stringlen = NAME_LEN - 1;   /* name too long */

		/* Copy and terminate string into hash name */
		tvb_memcpy(tvb, (guint8 *)hash_info->user_name, 0, stringlen);
		hash_info->user_name[stringlen] = '\0';

		col_append_str(pinfo->cinfo, COL_INFO, ", (User information)");
	}
}
Exemplo n.º 7
0
static void
dissect_cwids(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	tvbuff_t *wlan_tvb;
	proto_tree *ti, *cwids_tree;
	volatile int offset = 0;
	guint16 capturelen;
	void *pd_save;

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "CWIDS");
	col_set_str(pinfo->cinfo, COL_INFO, "Cwids: ");
	/* FIXME: col_set_fence(pinfo->cinfo, all-cols, only addr-cols?); */

	cwids_tree = NULL;

	while(tvb_length_remaining(tvb, offset) > 0) {
		ti = proto_tree_add_item(tree, proto_cwids, tvb, offset, 28, ENC_NA);
		cwids_tree = proto_item_add_subtree(ti, ett_cwids);

		proto_tree_add_item(cwids_tree, hf_cwids_version, tvb, offset, 2, ENC_BIG_ENDIAN);
		offset += 2;
		proto_tree_add_item(cwids_tree, hf_cwids_unknown1, tvb, offset, 7, ENC_NA);
		offset += 7;
		proto_tree_add_item(cwids_tree, hf_cwids_channel, tvb, offset, 1, ENC_BIG_ENDIAN);
		offset += 1;
		proto_tree_add_item(cwids_tree, hf_cwids_unknown2, tvb, offset, 6, ENC_NA);
		offset += 6;
		proto_tree_add_item(cwids_tree, hf_cwids_reallength, tvb, offset, 2, ENC_BIG_ENDIAN);
		offset += 2;
		capturelen = tvb_get_ntohs(tvb, offset);
		proto_tree_add_item(cwids_tree, hf_cwids_capturelen, tvb, offset, 2, ENC_BIG_ENDIAN);
		offset += 2;
		proto_tree_add_item(cwids_tree, hf_cwids_unknown3, tvb, offset, 8, ENC_NA);
		offset += 8;

		wlan_tvb = tvb_new_subset(tvb, offset, capturelen, capturelen);
		/* Continue after ieee80211 dissection errors */
		pd_save = pinfo->private_data;
		TRY {
			call_dissector(ieee80211_handle, wlan_tvb, pinfo, tree);
		} CATCH2(BoundsError, ReportedBoundsError) {

			expert_add_info_format(pinfo, NULL,
				PI_MALFORMED, PI_ERROR,
				"Malformed or short IEEE80211 subpacket");

			/*  Restore the private_data structure in case one of the
			 *  called dissectors modified it (and, due to the exception,
			 *  was unable to restore it).
			 */
			pinfo->private_data = pd_save;

			col_append_str(pinfo->cinfo, COL_INFO,
				" [Malformed or short IEEE80211 subpacket] " );
			col_set_fence(pinfo->cinfo, COL_INFO);
#if 0
	wlan_tvb = tvb_new_subset(tvb, offset, capturelen, capturelen);
			/* FIXME: Why does this throw an exception? */
			proto_tree_add_text(cwids_tree, wlan_tvb, offset, capturelen,
				"[Malformed or short IEEE80211 subpacket]");
#else
			tvb_new_subset(tvb, offset, capturelen, capturelen);
#endif
	;
		} ENDTRY;

		offset += capturelen;
	}
Exemplo n.º 8
0
void
show_exception(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
	       unsigned long exception, const char *exception_message)
{
	static const char dissector_error_nomsg[] =
		"Dissector writer didn't bother saying what the error was";
	proto_item *item;


	switch (exception) {

	case ScsiBoundsError:
		col_append_str(pinfo->cinfo, COL_INFO, "[SCSI transfer limited due to allocation_length too small]");
		/*item =*/ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0,
				"SCSI transfer limited due to allocation_length too small: %s truncated]", pinfo->current_proto);
		/* Don't record ScsiBoundsError exceptions as expert events - they merely
		 * reflect a normal SCSI condition.
		 * (any case where it's caused by something else is a bug). */
		/* expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Packet size limited");*/
		break;

	case BoundsError:
		col_append_str(pinfo->cinfo, COL_INFO, "[Packet size limited during capture]");
		/*item =*/ proto_tree_add_protocol_format(tree, proto_short, tvb, 0, 0,
				"[Packet size limited during capture: %s truncated]", pinfo->current_proto);
		/* Don't record BoundsError exceptions as expert events - they merely
		 * reflect a capture done with a snapshot length too short to capture
		 * all of the packet
		 * (any case where it's caused by something else is a bug). */
		/* expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR, "Packet size limited");*/
		break;

	case ReportedBoundsError:
		show_reported_bounds_error(tvb, pinfo, tree);
		break;

	case DissectorError:
		col_append_fstr(pinfo->cinfo, COL_INFO,
		    "[Dissector bug, protocol %s: %s]",
		    pinfo->current_proto,
		    exception_message == NULL ?
		        dissector_error_nomsg : exception_message);
		item = proto_tree_add_protocol_format(tree, proto_malformed, tvb, 0, 0,
		    "[Dissector bug, protocol %s: %s]",
		    pinfo->current_proto,
		    exception_message == NULL ?
		        dissector_error_nomsg : exception_message);
		g_warning("Dissector bug, protocol %s, in packet %u: %s",
		    pinfo->current_proto, pinfo->fd->num,
		    exception_message == NULL ?
		        dissector_error_nomsg : exception_message);
		expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR,
		    "%s",
		    exception_message == NULL ?
		        dissector_error_nomsg : exception_message);
		break;

	default:
		/* XXX - we want to know, if an unknown exception passed until here, don't we? */
		g_assert_not_reached();
	}
}
Exemplo n.º 9
0
static int
dissect_rtspmessage(tvbuff_t *tvb, int offset, packet_info *pinfo,
	proto_tree *tree)
{
	proto_tree		*rtsp_tree = NULL;
	proto_tree		*sub_tree = NULL;
	proto_item		*ti = NULL;
	const guchar		*line;
	gint			next_offset;
	const guchar		*linep, *lineend;
	int			orig_offset;
	int			first_linelen, linelen;
	int			line_end_offset;
	int			colon_offset;
	gboolean		is_request_or_reply;
	gboolean		body_requires_content_len;
	gboolean		saw_req_resp_or_header;
	guchar			c;
	rtsp_type_t		rtsp_type;
	gboolean		is_header;
	int			datalen;
	int			content_length;
	int			reported_datalen;
	int			value_offset;
	int			value_len;
	e164_info_t		e164_info;
	gint			rdt_feature_level = 0;
	gchar			*media_type_str_lower_case = NULL;
	int			semi_colon_offset;
	int			par_end_offset;

	/*
	 * Is this a request or response?
	 *
	 * Note that "tvb_find_line_end()" will return a value that
	 * is not longer than what's in the buffer, so the
	 * "tvb_get_ptr()" call won't throw an exception.
	 */
	first_linelen = tvb_find_line_end(tvb, offset,
	    tvb_ensure_length_remaining(tvb, offset), &next_offset,
	    FALSE);

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

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

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTSP");
	if (check_col(pinfo->cinfo, COL_INFO)) {
		/*
		 * Put the first line from the buffer into the summary
 		 * if it's an RTSP request or reply (but leave out the
		 * line terminator).
		 * Otherwise, just call it a continuation.
		 *
		 * Note that "tvb_find_line_end()" will return a value that
		 * is not longer than what's in the buffer, so the
		 * "tvb_get_ptr()" call won't throw an exception.
		 */
		line = tvb_get_ptr(tvb, offset, first_linelen);
		if (is_request_or_reply)
			if ( rtsp_type == RTSP_REPLY ) {
				col_set_str(pinfo->cinfo, COL_INFO, "Reply: ");
				col_append_str(pinfo->cinfo, COL_INFO,
					format_text(line, first_linelen));
			}
			else
				col_add_str(pinfo->cinfo, COL_INFO,
					format_text(line, first_linelen));

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

	}

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

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

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

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


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

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

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

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

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

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

			switch (c) {

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		/*
		 * We've processed "datalen" bytes worth of data
		 * (which may be no data at all); advance the
		 * offset past whatever data we've processed.
		 */
		offset += datalen;
	}
	return offset - orig_offset;
}
Exemplo n.º 10
0
static int dissect_dvb_s2_bb(tvbuff_t *tvb, int cur_off, proto_tree *tree, packet_info *pinfo)
{
    proto_item *ti;
    proto_tree *dvb_s2_bb_tree;

    guint8      input8, matype1;
    guint16     input16, bb_data_len = 0, user_packet_length;

    int         sub_dissected        = 0, flag_is_ms = 0, new_off = 0;

    static const int * bb_header_bitfields[] = {
        &hf_dvb_s2_bb_matype1_gs,
        &hf_dvb_s2_bb_matype1_mis,
        &hf_dvb_s2_bb_matype1_acm,
        &hf_dvb_s2_bb_matype1_issyi,
        &hf_dvb_s2_bb_matype1_npd,
        &hf_dvb_s2_bb_matype1_ro,
        NULL
    };

    col_append_str(pinfo->cinfo, COL_PROTOCOL, "BB ");
    col_append_str(pinfo->cinfo, COL_INFO, "Baseband ");

    /* create display subtree for the protocol */
    ti = proto_tree_add_item(tree, proto_dvb_s2_bb, tvb, cur_off, DVB_S2_BB_HEADER_LEN, ENC_NA);
    dvb_s2_bb_tree = proto_item_add_subtree(ti, ett_dvb_s2_bb);

    matype1 = tvb_get_guint8(tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1);
    new_off += 1;

    if (BIT_IS_CLEAR(matype1, DVB_S2_BB_MIS_POS))
        flag_is_ms = 1;

    proto_tree_add_bitmask_with_flags(dvb_s2_bb_tree, tvb, cur_off + DVB_S2_BB_OFFS_MATYPE1, hf_dvb_s2_bb_matype1,
        ett_dvb_s2_bb_matype1, bb_header_bitfields, ENC_BIG_ENDIAN, BMT_NO_FLAGS);

    input8 = tvb_get_guint8(tvb, cur_off + DVB_S2_BB_OFFS_MATYPE2);
    new_off += 1;
    if (flag_is_ms) {
        proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_matype2, tvb,
                                   cur_off + DVB_S2_BB_OFFS_MATYPE2, 1, input8, "Input Stream Identifier (ISI): %d",
                                   input8);
    } else {
        proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_matype2, tvb,
                                   cur_off + DVB_S2_BB_OFFS_MATYPE2, 1, input8, "reserved");
    }

    user_packet_length = input16 = tvb_get_ntohs(tvb, cur_off + DVB_S2_BB_OFFS_UPL);
    new_off += 2;

    proto_tree_add_uint_format(dvb_s2_bb_tree, hf_dvb_s2_bb_upl, tvb,
                               cur_off + DVB_S2_BB_OFFS_UPL, 2, input16, "User Packet Length: %d bits (%d bytes)",
                               (guint16) input16, (guint16) input16 / 8);

    bb_data_len = input16 = tvb_get_ntohs(tvb, cur_off + DVB_S2_BB_OFFS_DFL);
    bb_data_len /= 8;
    new_off += 2;

    proto_tree_add_uint_format_value(dvb_s2_bb_tree, hf_dvb_s2_bb_dfl, tvb,
                               cur_off + DVB_S2_BB_OFFS_DFL, 2, input16, "%d bits (%d bytes)", input16, input16 / 8);

    new_off += 1;
    proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_sync, tvb, cur_off + DVB_S2_BB_OFFS_SYNC, 1, ENC_BIG_ENDIAN);

    new_off += 2;
    proto_tree_add_item(dvb_s2_bb_tree, hf_dvb_s2_bb_syncd, tvb, cur_off + DVB_S2_BB_OFFS_SYNCD, 2, ENC_BIG_ENDIAN);

    new_off += 1;
    proto_tree_add_checksum(dvb_s2_bb_tree, tvb, cur_off + DVB_S2_BB_OFFS_CRC, hf_dvb_s2_bb_crc, hf_dvb_s2_bb_crc_status, &ei_dvb_s2_bb_crc, pinfo,
        compute_crc8(tvb, DVB_S2_BB_HEADER_LEN - 1, cur_off), ENC_NA, PROTO_CHECKSUM_VERIFY);

    switch (matype1 & DVB_S2_BB_TSGS_MASK) {
    case DVB_S2_BB_TSGS_GENERIC_CONTINUOUS:
        /* Check GSE constraints on the BB header per 9.2.1 of ETSI TS 102 771 */
        if (BIT_IS_SET(matype1, DVB_S2_BB_ISSYI_POS)) {
            expert_add_info(pinfo, ti, &ei_dvb_s2_bb_issy_invalid);
        }
        if (BIT_IS_SET(matype1, DVB_S2_BB_NPD_POS)) {
            expert_add_info(pinfo, ti, &ei_dvb_s2_bb_npd_invalid);
        }
        if (user_packet_length != 0x0000) {
            expert_add_info_format(pinfo, ti, &ei_dvb_s2_bb_upl_invalid,
                "UPL is 0x%04x. It must be 0x0000 for GSE packets.", user_packet_length);
        }


        while (bb_data_len) {
            /* start DVB-GSE dissector */
            sub_dissected = dissect_dvb_s2_gse(tvb, cur_off + new_off, tree, pinfo, bb_data_len);
            new_off += sub_dissected;

            if ((sub_dissected <= bb_data_len) && (sub_dissected >= DVB_S2_GSE_MINSIZE)) {
                bb_data_len -= sub_dissected;
                if (bb_data_len < DVB_S2_GSE_MINSIZE)
                    bb_data_len = 0;
            } else {
                bb_data_len = 0;
            }
        }
        break;

    case DVB_S2_BB_TSGS_GENERIC_PACKETIZED:
        proto_tree_add_item(tree, hf_dvb_s2_bb_packetized, tvb, cur_off + new_off, bb_data_len, ENC_NA);
        new_off += bb_data_len;
        break;

    case DVB_S2_BB_TSGS_TRANSPORT_STREAM:
        proto_tree_add_item(tree, hf_dvb_s2_bb_transport, tvb, cur_off + new_off, bb_data_len, ENC_NA);
        new_off += bb_data_len;
        break;

    default:
        proto_tree_add_item(tree, hf_dvb_s2_bb_reserved, tvb, cur_off + new_off,bb_data_len, ENC_NA);
        new_off += bb_data_len;
        expert_add_info(pinfo, ti, &ei_dvb_s2_bb_reserved);
        break;
    }

    return new_off;
}
Exemplo n.º 11
0
static void
dissect_drda(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*drda_tree = NULL;
	proto_tree	*drdaroot_tree = NULL;
	proto_item	*ti = NULL;
	gint offset = 0;
	static gint iPreviousFrameNumber = -1;

	guint16 iCommand;
	guint16 iLength;

	guint8 iFormatFlags;
	guint8 iDSSType;
	guint8 iDSSFlags;

	guint16 iParameterCP;
	proto_tree	*drda_tree_sub;
	gint iLengthParam;

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRDA");
	if (check_col(pinfo->cinfo, COL_INFO))
	{
		/* This is a trick to know whether this is the first PDU in this packet or not */
		if (iPreviousFrameNumber != (gint) pinfo->fd->num)
			col_clear(pinfo->cinfo, COL_INFO);
		else
			col_append_str(pinfo->cinfo, COL_INFO, " | ");
	}
	iPreviousFrameNumber = pinfo->fd->num;
	if (tvb_length(tvb) >= 10)
	{
		iCommand = tvb_get_ntohs(tvb, offset + 8);
		iLength = tvb_get_ntohs(tvb, offset + 0);

		if (check_col(pinfo->cinfo, COL_INFO)) 
		{
			col_append_str(pinfo->cinfo, COL_INFO, val_to_str(iCommand, drda_opcode_abbr, "Unknown (0x%02x)"));
		}

		if (tree)
		{
			ti = proto_tree_add_item(tree, proto_drda, tvb, offset, -1, FALSE);
			proto_item_append_text(ti, " (%s)", val_to_str(iCommand, drda_opcode_vals, "Unknown (0x%02x)"));
			drdaroot_tree = proto_item_add_subtree(ti, ett_drda);

			ti = proto_tree_add_text(drdaroot_tree, tvb, offset, 10, DRDA_TEXT_DDM);
			proto_item_append_text(ti, " (%s)", val_to_str(iCommand, drda_opcode_abbr, "Unknown (0x%02x)"));
			drda_tree = proto_item_add_subtree(ti, ett_drda_ddm);

			proto_tree_add_item(drda_tree, hf_drda_ddm_length, tvb, offset + 0, 2, FALSE);
			proto_tree_add_item(drda_tree, hf_drda_ddm_magic, tvb, offset + 2, 1, FALSE);

			{
				drda_tree_sub = NULL;
				iFormatFlags = tvb_get_guint8(tvb, offset + 3);
				iDSSType = iFormatFlags & 0x0F;
				iDSSFlags = iFormatFlags >> 4;

				ti = proto_tree_add_item(drda_tree, hf_drda_ddm_format, tvb, offset + 3, 1, FALSE);
				drda_tree_sub = proto_item_add_subtree(ti, ett_drda_ddm_format);

				proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_reserved, tvb, offset + 3, 1, iDSSFlags); 
				proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_chained, tvb, offset + 3, 1, iDSSFlags);
				proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_errcont, tvb, offset + 3, 1, iDSSFlags);
				proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_samecorr, tvb, offset + 3, 1, iDSSFlags);
				proto_tree_add_uint(drda_tree_sub, hf_drda_ddm_fmt_dsstyp, tvb, offset + 3, 1, iDSSType);
			}

			proto_tree_add_item(drda_tree, hf_drda_ddm_rc, tvb, offset + 4, 2, FALSE);
			proto_tree_add_item(drda_tree, hf_drda_ddm_length2, tvb, offset + 6, 2, FALSE);
			proto_tree_add_item(drda_tree, hf_drda_ddm_codepoint, tvb, offset + 8, 2, FALSE);

			/* The number of attributes is variable */
			for (offset = 10; offset <= iLength; )
			{
				if (tvb_length_remaining(tvb, offset) >= 2)
				{
					iLengthParam = tvb_get_ntohs(tvb, offset + 0);
					if (iLengthParam == 0 || iLengthParam == 1) iLengthParam = iLength - 10;
					if (tvb_length_remaining(tvb, offset) >= iLengthParam)
					{
						drda_tree_sub = NULL;
						iParameterCP = tvb_get_ntohs(tvb, offset + 2);
						ti = proto_tree_add_text(drdaroot_tree, tvb, offset, iLengthParam, DRDA_TEXT_PARAM);
						proto_item_append_text(ti, " (%s)", val_to_str(iParameterCP, drda_opcode_vals, "Unknown (0x%02x)"));
						drda_tree_sub = proto_item_add_subtree(ti, ett_drda_param);
						proto_tree_add_item(drda_tree_sub, hf_drda_param_length, tvb, offset, 2, FALSE);
						proto_tree_add_item(drda_tree_sub, hf_drda_param_codepoint, tvb, offset + 2, 2, FALSE);
						proto_tree_add_item(drda_tree_sub, hf_drda_param_data, tvb, offset + 4, iLengthParam - 4, FALSE);
						proto_tree_add_item(drda_tree_sub, hf_drda_param_data_ebcdic, tvb, offset + 4, iLengthParam - 4, FALSE);
						if (iCommand == DRDA_CP_SQLSTT)
						{
							/* Extract SQL statement from packet */
							tvbuff_t* next_tvb = NULL;
							next_tvb = tvb_new_subset(tvb, offset + 4, iLengthParam - 4, iLengthParam - 4);
							add_new_data_source(pinfo, next_tvb, "SQL statement");
							proto_tree_add_item(drdaroot_tree, hf_drda_sqlstatement, next_tvb, 0, iLengthParam - 5, FALSE);
							proto_tree_add_item(drdaroot_tree, hf_drda_sqlstatement_ebcdic, next_tvb, 0, iLengthParam - 4, FALSE);
						}
					}					
					offset += iLengthParam;
				}
				else
				{
					break;
				}
			}
		}
	}
Exemplo n.º 12
0
/* *** Code to actually dissect the packets *** */
static int dissect_dvb_s2_gse(tvbuff_t *tvb, int cur_off, proto_tree *tree, packet_info *pinfo, int bytes_available)
{
    int         new_off                      = 0;
    int         frag_len;
    guint16     gse_hdr, data_len, padding_len, gse_proto = 0;

    proto_item *ti;
    proto_tree *dvb_s2_gse_tree;

    tvbuff_t   *next_tvb;

    static const int * gse_header_bitfields[] = {
        &hf_dvb_s2_gse_hdr_start,
        &hf_dvb_s2_gse_hdr_stop,
        &hf_dvb_s2_gse_hdr_labeltype,
        &hf_dvb_s2_gse_hdr_length,
        NULL
    };

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

    /* get the GSE header */
    gse_hdr = tvb_get_ntohs(tvb, cur_off + DVB_S2_GSE_OFFS_HDR);

    /* check if this is just padding, which takes up the rest of the frame */
    if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) &&
        BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS) &&
        BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) {

        padding_len = bytes_available;
        proto_tree_add_uint_format(tree, hf_dvb_s2_gse_padding, tvb, cur_off + new_off, padding_len, padding_len,
                                   "DVB-S2 GSE Padding, Length: %d", padding_len);
        col_append_str(pinfo->cinfo, COL_INFO, " pad");
        new_off += padding_len;

        return new_off;
    } else {
        /* Not padding, parse as a GSE Header */
        new_off += 2;
        frag_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK)+2;
        ti = proto_tree_add_item(tree, proto_dvb_s2_gse, tvb, cur_off, frag_len, ENC_NA);
        dvb_s2_gse_tree = proto_item_add_subtree(ti, ett_dvb_s2_gse);

        proto_tree_add_bitmask_with_flags(dvb_s2_gse_tree, tvb, cur_off + DVB_S2_GSE_OFFS_HDR, hf_dvb_s2_gse_hdr,
            ett_dvb_s2_gse_hdr, gse_header_bitfields, ENC_BIG_ENDIAN, BMT_NO_TFS);

        if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) || BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {

            proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_fragid, tvb, cur_off + new_off, 1, ENC_BIG_ENDIAN);

            new_off += 1;
        }
        if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {

            proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_totlength, tvb, cur_off + new_off, 2, ENC_BIG_ENDIAN);
            col_append_str(pinfo->cinfo, COL_INFO, "(frag) ");

            new_off += 2;
        }
        if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_START_POS)) {
            gse_proto = tvb_get_ntohs(tvb, cur_off + new_off);

            proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_proto, tvb, cur_off + new_off, 2, ENC_BIG_ENDIAN);

            new_off += 2;

            if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) && BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) {
                /* 6 byte label */
                if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS))
                    col_append_str(pinfo->cinfo, COL_INFO, "6 ");

                proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_label6, tvb, cur_off + new_off, 6, ENC_NA);

                new_off += 6;
            } else if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS1) &&
                       BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_LABELTYPE_POS2)) {
                /* 3 byte label */
                if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS))
                    col_append_str(pinfo->cinfo, COL_INFO, "3 ");

                proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_label3, tvb, cur_off + new_off, 3, ENC_BIG_ENDIAN);

                new_off += 3;
            } else {
                /* 0 byte label */
                if (BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS))
                    col_append_str(pinfo->cinfo, COL_INFO, "0 ");
            }
            if (gse_proto < 0x0600 && gse_proto >= 0x100) {
                /* Only display optional extension headers */
                /* TODO: needs to be tested */

                /* TODO: implementation needs to be checked (len of ext-header??) */
                proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_exthdr, tvb, cur_off + new_off, 1, ENC_BIG_ENDIAN);

                new_off += 1;
            }
        }
        else
        {
            /* correct cinfo */
            col_append_str(pinfo->cinfo, COL_INFO, "(frag) ");
        }

        next_tvb = tvb_new_subset_remaining(tvb, cur_off + new_off);

        if (dvb_s2_full_dissection)
        {
            switch (gse_proto) {
            case ETHERTYPE_IP:
                new_off += call_dissector(ip_handle, next_tvb, pinfo, tree);
                break;
            case ETHERTYPE_IPv6:
                new_off += call_dissector(ipv6_handle, next_tvb, pinfo, tree);
                break;
            default:
                if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {
                    data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN;
                } else
                    data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE);

                proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA);
                new_off += data_len;
                break;
            }
        }
        else
        {
            if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {
                data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE) - DVB_S2_GSE_CRC32_LEN;
            } else
                data_len = (gse_hdr & DVB_S2_GSE_HDR_LENGTH_MASK) - (new_off - DVB_S2_GSE_MINSIZE);

            proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_data, tvb, cur_off + new_off, data_len, ENC_NA);
            new_off += data_len;
        }

        /* add crc32 if last fragment */
        if (BIT_IS_CLEAR(gse_hdr, DVB_S2_GSE_HDR_START_POS) && BIT_IS_SET(gse_hdr, DVB_S2_GSE_HDR_STOP_POS)) {
            proto_tree_add_item(dvb_s2_gse_tree, hf_dvb_s2_gse_crc32, tvb, cur_off + new_off, DVB_S2_GSE_CRC32_LEN, ENC_BIG_ENDIAN);
            new_off += DVB_S2_GSE_CRC32_LEN;
        }
    }

    return new_off;
}
Exemplo n.º 13
0
/* The dissector itself */
static void dissect_chdr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    // Here are all the variables
    proto_item *item;
    proto_item *stream_item;
    proto_tree *chdr_tree;
    proto_item *header_item;
    proto_tree *header_tree;
    proto_tree *stream_tree;
    proto_item *response_item;
    proto_tree *response_tree;
    proto_item *cmd_item;
    proto_tree *cmd_tree;
    gint len;

    gint flag_offset;
    guint8 *bytes;
    guint8 hdr_bits = 0;
    guint8 pkt_type = 0;
    gboolean flag_has_time = 0;
    gboolean flag_is_data = 0;
    gboolean flag_is_fc = 0;
    gboolean flag_is_cmd = 0;
    gboolean flag_is_resp = 0;
    gboolean flag_is_eob = 0;
    gboolean flag_is_error = 0;
    unsigned long long timestamp;
    gboolean is_network;
    gint endianness;
    gint id_pos_usb[4] = {7, 6, 5, 4};
    gint id_pos_net[4] = {4, 5, 6, 7};
    gint id_pos[4] = {7, 6, 5, 4};

    if(pinfo->match_uint == CHDR_PORT){
        is_network = TRUE;
        flag_offset = 0;
        endianness = ENC_BIG_ENDIAN;
        memcpy(id_pos, id_pos_net, 4 * sizeof(gint));
    }
    else{   // Parsing a USB capture
        is_network = FALSE;
        flag_offset = 3;
        endianness = ENC_LITTLE_ENDIAN;
        memcpy(id_pos, id_pos_usb, 4 * sizeof(gint));
    }

    len = tvb_reported_length(tvb);

    col_append_str(pinfo->cinfo, COL_PROTOCOL, "/CHDR");
    /* This throws a warning: */
    /*col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "CHDR", tvb_format_text_wsp(tvb, 0, len));*/
    col_append_sep_fstr(pinfo->cinfo, COL_INFO, NULL, "CHDR");

    if (tree){
        int chdr_size = -1;

        if (len >= 4){
            chdr_size = 8;
            bytes = tvb_get_string(wmem_packet_scope(), tvb, 0, 4);
	    hdr_bits = (bytes[flag_offset] & 0xF0) >> 4;
	    pkt_type = hdr_bits >> 2;
	    flag_is_data = (pkt_type == 0);
	    flag_is_fc = (pkt_type == 1);
	    flag_is_cmd = (pkt_type == 2);
	    flag_is_resp = (pkt_type == 3);
	    flag_is_eob = flag_is_data && (hdr_bits & 0x1);
	    flag_is_error = flag_is_resp && (hdr_bits & 0x1);
            flag_has_time = hdr_bits & 0x2;
            if (flag_has_time)
                chdr_size += 8; // 64-bit timestamp
        }

        /* Start with a top-level item to add everything else to */
        item = proto_tree_add_item(tree, proto_chdr, tvb, 0, min(len, chdr_size), ENC_NA);

        if (len >= 4) {
            chdr_tree = proto_item_add_subtree(item, ett_chdr);

            /* Header info. First, a top-level header tree item: */
            header_item = proto_tree_add_item(chdr_tree, hf_chdr_hdr, tvb, flag_offset, 1, endianness);
            header_tree = proto_item_add_subtree(header_item, ett_chdr_header);
            proto_item_append_text(header_item, ", Packet type: %s",
                val_to_str(hdr_bits & 0xD, CHDR_PACKET_TYPES, "Unknown (0x%x)")
            );
            /* Let us query hdr.type */
            proto_tree_add_string(
                header_tree, hf_chdr_type, tvb, flag_offset, 1,
                val_to_str(hdr_bits & 0xD, CHDR_PACKET_TYPES_SHORT, "invalid")
            );
            /* And other flags */
            proto_tree_add_boolean(header_tree, hf_chdr_has_time, tvb, flag_offset, 1, flag_has_time);
            if (flag_is_data) {
                proto_tree_add_boolean(header_tree, hf_chdr_eob, tvb, flag_offset, 1, flag_is_eob);
            }
            if (flag_is_resp) {
                proto_tree_add_boolean(header_tree, hf_chdr_error, tvb, flag_offset, 1, flag_is_error);
            }

            /* These lines add sequence, packet_size and stream ID */
            proto_tree_add_item(chdr_tree, hf_chdr_sequence, tvb, (is_network ? 0:2), 2, endianness);
            proto_tree_add_item(chdr_tree, hf_chdr_packet_size, tvb, (is_network ? 2:0), 2, endianness);

            if (len >= 8){
                /* stream id can be broken down to 4 sections. these are collapsed in a subtree */
                stream_item = proto_tree_add_item(chdr_tree, hf_chdr_stream_id, tvb, 4, 4, endianness);
                stream_tree = proto_item_add_subtree(stream_item, ett_chdr_id);
                proto_tree_add_item(stream_tree, hf_chdr_src_dev, tvb, id_pos[0], 1, ENC_NA);
                proto_tree_add_item(stream_tree, hf_chdr_src_ep,  tvb, id_pos[1], 1, ENC_NA);
                proto_tree_add_item(stream_tree, hf_chdr_dst_dev, tvb, id_pos[2], 1, ENC_NA);
                proto_tree_add_item(stream_tree, hf_chdr_dst_ep,  tvb, id_pos[3], 1, ENC_NA);

                /* Block ports (only add them if address points to a device) */
                bytes = tvb_get_string(wmem_packet_scope(), tvb, 0, 8);
		if (bytes[id_pos[0]] != 0) {
                    proto_tree_add_item(stream_tree, hf_chdr_src_blockport, tvb, id_pos[1], 1, ENC_NA);
		}
		if (bytes[id_pos[2]] != 0) {
                    proto_tree_add_item(stream_tree, hf_chdr_dst_blockport, tvb, id_pos[3], 1, ENC_NA);
		}

		/* Append SID in sid_t hex format */
                proto_item_append_text(stream_item, " (%02X:%02X>%02X:%02X)",
                    bytes[id_pos[0]],
                    bytes[id_pos[1]],
                    bytes[id_pos[2]],
                    bytes[id_pos[3]]
                );

                /* if has_time flag is present interpret timestamp */
                if ((flag_has_time) && (len >= 16)){
                    if (is_network)
                        item = proto_tree_add_item(chdr_tree, hf_chdr_timestamp, tvb, 8, 8, endianness);
                    else{
                        bytes = (guint8*) tvb_get_string(wmem_packet_scope(), tvb, 8, sizeof(unsigned long long));
                        timestamp = get_timestamp(bytes, sizeof(unsigned long long));
                        proto_tree_add_uint64(chdr_tree, hf_chdr_timestamp, tvb, 8, 8, timestamp);
                    }
                }

                int remaining_bytes = (len - chdr_size);
                int show_raw_payload = (remaining_bytes > 0);

                if (flag_is_cmd && remaining_bytes == 8) {
                    cmd_item = proto_tree_add_item(chdr_tree, hf_chdr_cmd, tvb, chdr_size, 8, endianness);
                    cmd_tree = proto_item_add_subtree(cmd_item, ett_chdr_cmd);
                    proto_tree_add_item(cmd_tree, hf_chdr_cmd_address, tvb, chdr_size,     4, endianness);
                    proto_tree_add_item(cmd_tree, hf_chdr_cmd_value,   tvb, chdr_size + 4, 4, endianness);
                } else if (flag_is_resp) {
                    response_item = proto_tree_add_item(chdr_tree, hf_chdr_ext_response, tvb, chdr_size, 8, endianness);
                    response_tree = proto_item_add_subtree(response_item, ett_chdr_response);

                    proto_tree_add_item(response_tree, hf_chdr_ext_status_code, tvb, chdr_size, 4, endianness);
                    /* This will show the 12-bits of sequence ID in the last 2 bytes */
                    proto_tree_add_item(response_tree, hf_chdr_ext_seq_num, tvb, (chdr_size + 4 + (is_network ? 2 : 0)), 2, endianness);
                } else if (show_raw_payload) {
                    proto_tree_add_item(chdr_tree, hf_chdr_payload, tvb, chdr_size, -1, ENC_NA);
                }
            }
        }
    }
Exemplo n.º 14
0
/* Parse Short Message, only if UDH present
 * (otherwise this function is not called).
 * Call WSP dissector if port matches WSP traffic.
 */
static void
parse_gsm_sms_ud_message(proto_tree *sm_tree, tvbuff_t *tvb, packet_info *pinfo,
        proto_tree *top_tree)
{
    tvbuff_t      *sm_tvb                    = NULL;
    proto_item    *ti;
    proto_tree    *subtree, *tree;
    guint8         udh_len, udh, len;
    guint          sm_len                    = tvb_reported_length(tvb);
    guint          sm_data_len;
    guint32        i                         = 0;
    /* Multiple Messages UDH */
    gboolean       is_fragmented             = FALSE;
    fragment_head *fd_sm                     = NULL;
    guint16        sm_id                     = 0;
    guint16        frags                     = 0;
    guint16        frag                      = 0;
    gboolean       save_fragmented           = FALSE;
    gboolean       try_gsm_sms_ud_reassemble = FALSE;
    /* SMS Message reassembly */
    gboolean       reassembled               = FALSE;
    guint32        reassembled_in            = 0;
    /* Port Number UDH */
    guint16        p_src                     = 0;
    guint16        p_dst                     = 0;
    gboolean       ports_available           = FALSE;

    udh_len = tvb_get_guint8(tvb, i++);
    ti   = proto_tree_add_uint(sm_tree, hf_gsm_sms_udh_length, tvb, 0, 1, udh_len);
    tree = proto_item_add_subtree(ti, ett_udh);
    while (i < udh_len) {
        udh = tvb_get_guint8(tvb, i++);
        len = tvb_get_guint8(tvb, i++);
        subtree = proto_tree_add_uint(tree, hf_gsm_sms_udh_iei,
                tvb, i-2, 2+len, udh);
        switch (udh) {
            case 0x00: /* Multiple messages - 8-bit message ID */
                if (len == 3) {
                    sm_id = tvb_get_guint8(tvb, i++);
                    frags = tvb_get_guint8(tvb, i++);
                    frag  = tvb_get_guint8(tvb, i++);
                    if (frags > 1)
                        is_fragmented = TRUE;
                    proto_item_append_text(subtree,
                            ": message %u, part %u of %u", sm_id, frag, frags);
                    subtree = proto_item_add_subtree(subtree,
                            ett_udh_ie);
                    proto_tree_add_uint(subtree,
                            hf_gsm_sms_udh_multiple_messages_msg_id,
                            tvb, i-3, 1, sm_id);
                    proto_tree_add_uint(subtree,
                            hf_gsm_sms_udh_multiple_messages_msg_parts,
                            tvb, i-2, 1, frags);
                    proto_tree_add_uint(subtree,
                            hf_gsm_sms_udh_multiple_messages_msg_part,
                            tvb, i-1, 1, frag);
                } else {
                    proto_item_append_text(subtree, " - Invalid format!");
                    i += len;
                }
                break;

            case 0x08: /* Multiple messages - 16-bit message ID */
                if (len == 4) {
                    sm_id = tvb_get_ntohs(tvb, i); i += 2;
                    frags = tvb_get_guint8(tvb, i++);
                    frag  = tvb_get_guint8(tvb, i++);
                    if (frags > 1)
                        is_fragmented = TRUE;
                    proto_item_append_text(subtree,
                            ": message %u, part %u of %u", sm_id, frag, frags);
                    subtree = proto_item_add_subtree(subtree,
                            ett_udh_ie);
                    proto_tree_add_uint(subtree,
                            hf_gsm_sms_udh_multiple_messages_msg_id,
                            tvb, i-4, 2, sm_id);
                    proto_tree_add_uint(subtree,
                            hf_gsm_sms_udh_multiple_messages_msg_parts,
                            tvb, i-2, 1, frags);
                    proto_tree_add_uint(subtree,
                            hf_gsm_sms_udh_multiple_messages_msg_part,
                            tvb, i-1, 1, frag);
                } else {
                    proto_item_append_text(subtree, " - Invalid format!");
                    i += len;
                }
                break;

            case 0x04: /* Port Number UDH - 8-bit address */
                if (len == 2) { /* Port fields */
                    p_dst = tvb_get_guint8(tvb, i++);
                    p_src = tvb_get_guint8(tvb, i++);
                    proto_item_append_text(subtree,
                            ": source port %u, destination port %u",
                            p_src, p_dst);
                    subtree = proto_item_add_subtree(subtree, ett_udh_ie);
                    proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_dst,
                            tvb, i-2, 1, p_dst);
                    proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_src,
                            tvb, i-1, 1, p_src);
                    ports_available = TRUE;
                } else {
                    proto_item_append_text(subtree, " - Invalid format!");
                    i += len;
                }
                break;

            case 0x05: /* Port Number UDH - 16-bit address */
                if (len == 4) { /* Port fields */
                    p_dst = tvb_get_ntohs(tvb, i); i += 2;
                    p_src = tvb_get_ntohs(tvb, i); i += 2;
                    proto_item_append_text(subtree,
                            ": source port %u, destination port %u",
                            p_src, p_dst);
                    subtree = proto_item_add_subtree(subtree, ett_udh_ie);
                    proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_dst,
                            tvb, i-4, 2, p_dst);
                    proto_tree_add_uint(subtree, hf_gsm_sms_udh_ports_src,
                            tvb, i-2, 2, p_src);
                    ports_available = TRUE;
                } else {
                    proto_item_append_text(subtree, " - Invalid format!");
                    i += len;
                }
                break;

            default:
                i += len;
                break;
        }
    }
    if (tvb_reported_length_remaining(tvb, i) <= 0)
        return; /* No more data */

    /*
     * XXX - where does the "1" come from?  If it weren't there,
     * "sm_data_len" would, I think, be the same as
     * "tvb_reported_length_remaining(tvb, i)".
     *
     * I think that the above check ensures that "sm_len" won't
     * be less than or equal to "udh_len", so it ensures that
     * "sm_len" won't be less than "1 + udh_len", so we don't
     * have to worry about "sm_data_len" being negative.
     */
    sm_data_len = sm_len - (1 + udh_len);
    if (sm_data_len == 0)
        return; /* no more data */

    /*
     * Try reassembling the packets.
     * XXX - fragment numbers are 1-origin, but the fragment number
     * field could be 0.
     * Should we flag a fragmented message with a fragment number field
     * of 0?
     * What if the fragment count is 0?  Should we flag that as well?
     */
    if (is_fragmented && frag != 0 && frags != 0 &&
        tvb_bytes_exist(tvb, i, sm_data_len)) {
        try_gsm_sms_ud_reassemble = TRUE;
        save_fragmented = pinfo->fragmented;
        pinfo->fragmented = TRUE;
        fd_sm = fragment_add_seq_check(&sm_reassembly_table,
                tvb, i,
                pinfo,
                sm_id,                /* guint32 ID for fragments belonging together */
                NULL,
                frag-1,               /* guint32 fragment sequence number */
                sm_data_len,          /* guint32 fragment length */
                (frag != frags));     /* More fragments? */
        if (fd_sm) {
            reassembled    = TRUE;
            reassembled_in = fd_sm->reassembled_in;
        }
        sm_tvb = process_reassembled_data(tvb, i, pinfo,
            "Reassembled Short Message", fd_sm, &sm_frag_items,
            NULL, sm_tree);
        if (reassembled) { /* Reassembled */
            col_append_str(pinfo->cinfo, COL_INFO,
                        " (Short Message Reassembled)");
        } else {
            /* Not last packet of reassembled Short Message */
            col_append_fstr(pinfo->cinfo, COL_INFO,
                    " (Short Message fragment %u of %u)", frag, frags);
        }
    } /* Else: not fragmented */

    if (! sm_tvb) /* One single Short Message, or not reassembled */
        sm_tvb = tvb_new_subset_remaining(tvb, i);
    /* Try calling a subdissector */
    if (sm_tvb) {
        if ((reassembled && pinfo->fd->num == reassembled_in)
            || frag==0 || (frag==1 && try_dissect_1st_frag)) {
            /* Try calling a subdissector only if:
             *  - the Short Message is reassembled in this very packet,
             *  - the Short Message consists of only one "fragment",
             *  - the preference "Always Try Dissection for 1st SM fragment"
             *    is switched on, and this is the SM's 1st fragment. */
            if (ports_available) {
                gboolean disallow_write = FALSE; /* TRUE if we changed writability
                                    of the columns of the summary */
                if (prevent_subdissectors_changing_columns && col_get_writable(pinfo->cinfo)) {
                    disallow_write = TRUE;
                    col_set_writable(pinfo->cinfo, FALSE);
                }

                if (port_number_udh_means_wsp) {
                    call_dissector(wsp_handle, sm_tvb, pinfo, top_tree);
                } else {
                    if (! dissector_try_uint(gsm_sms_dissector_table, p_src,
                                sm_tvb, pinfo, top_tree)) {
                        if (! dissector_try_uint(gsm_sms_dissector_table, p_dst,
                                    sm_tvb, pinfo, top_tree)) {
                            if (sm_tree) { /* Only display if needed */
                                proto_tree_add_text(sm_tree, sm_tvb, 0, -1,
                                        "Short Message body");
                            }
                        }
                    }
                }

                if (disallow_write)
                    col_set_writable(pinfo->cinfo, TRUE);
            } else { /* No ports IE */
                proto_tree_add_text(sm_tree, sm_tvb, 0, -1,
                        "Short Message body");
            }
        } else {
            /* The packet is not reassembled,
             * or it is reassembled in another packet */
            proto_tree_add_text(sm_tree, sm_tvb, 0, -1,
                    "Unreassembled Short Message fragment %u of %u",
                    frag, frags);
        }
    }

    if (try_gsm_sms_ud_reassemble) /* Clean up defragmentation */
        pinfo->fragmented = save_fragmented;
    return;
}
Exemplo n.º 15
0
static void
dissect_rsh(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	/* Set up structures needed to add the protocol subtree and manage it */
	proto_item *ti;
	proto_tree *rsh_tree=NULL;

	/* Variables for extracting and displaying data from the packet */
	guchar *field_stringz; /* Temporary storage for each field we extract */

	gint length;
	guint offset = 0;
	conversation_t *conversation;
	rsh_hash_entry_t *hash_info;

	conversation = find_or_create_conversation(pinfo);

	/* Retrieve information from conversation
	 * or add it if it isn't there yet
	 */
	hash_info = conversation_get_proto_data(conversation, proto_rsh);
	if(!hash_info){
		hash_info = se_alloc(sizeof(rsh_hash_entry_t));

		hash_info->first_packet_number = pinfo->fd->num;
		hash_info->second_packet_number = 0;
		hash_info->third_packet_number  = 0;
		hash_info->fourth_packet_number  = 0;

		hash_info->state = WAIT_FOR_STDERR_PORT; /* The first field we'll see */

		/* Start with empty username and command strings */
		hash_info->client_username=NULL;
		hash_info->server_username=NULL;
		hash_info->command=NULL;

		/* These will be set on the first pass by the first
		 * four packets of the conversation
		 */
		hash_info->first_packet_state  = NONE;
		hash_info->second_packet_state = NONE;
		hash_info->third_packet_state  = NONE;
		hash_info->fourth_packet_state  = NONE;

		conversation_add_proto_data(conversation, proto_rsh, hash_info);
	}

	/* Store the number of the first three packets of this conversation
	 * as we reach them the first time */

	if(!hash_info->second_packet_number
	&& pinfo->fd->num > hash_info->first_packet_number){
		/* We're on the second packet of the conversation */
		hash_info->second_packet_number = pinfo->fd->num;
	} else if(hash_info->second_packet_number
	 && !hash_info->third_packet_number
	 && pinfo->fd->num > hash_info->second_packet_number) {
		/* We're on the third packet of the conversation */
		hash_info->third_packet_number = pinfo->fd->num;
	} else if(hash_info->third_packet_number
	 && !hash_info->fourth_packet_number
	 && pinfo->fd->num > hash_info->third_packet_number) {
		/* We're on the fourth packet of the conversation */
		hash_info->fourth_packet_number = pinfo->fd->num;
	}

	/* Save this packet's state so we can retrieve it if this packet
	 * is selected again later.  If the packet's state was already stored,
	 * then retrieve it */
	if(pinfo->fd->num == hash_info->first_packet_number){
		if(hash_info->first_packet_state == NONE){
			hash_info->first_packet_state = hash_info->state;
		} else {
			hash_info->state = hash_info->first_packet_state;
		}
	}

	if(pinfo->fd->num == hash_info->second_packet_number){
		if(hash_info->second_packet_state == NONE){
			hash_info->second_packet_state = hash_info->state;
		} else {
			hash_info->state = hash_info->second_packet_state;
		}
	}

	if(pinfo->fd->num == hash_info->third_packet_number){
		if(hash_info->third_packet_state == NONE){
			hash_info->third_packet_state = hash_info->state;
		} else {
			hash_info->state = hash_info->third_packet_state;
		}
	}

	if(pinfo->fd->num == hash_info->fourth_packet_number){
		if(hash_info->fourth_packet_state == NONE){
			hash_info->fourth_packet_state = hash_info->state;
		} else {
			hash_info->state = hash_info->fourth_packet_state;
		}
	}

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

	if(check_col(pinfo->cinfo, COL_INFO)){
		/* First, clear the info column */
		col_clear(pinfo->cinfo, COL_INFO);

		/* Client username */
		if(hash_info->client_username && preference_info_show_client_username == TRUE){
			col_append_fstr(pinfo->cinfo, COL_INFO, "Client username:%s ", hash_info->client_username);
		}

		/* Server username */
		if(hash_info->server_username && preference_info_show_server_username == TRUE){
			col_append_fstr(pinfo->cinfo, COL_INFO, "Server username:%s ", hash_info->server_username);
		}

		/* Command */
		if(hash_info->command && preference_info_show_command == TRUE){
			col_append_fstr(pinfo->cinfo, COL_INFO, "Command:%s ", hash_info->command);
		}
	}

	/* create display subtree for the protocol */
	ti = proto_tree_add_item(tree, proto_rsh, tvb, 0, -1, ENC_NA);
	rsh_tree = proto_item_add_subtree(ti, ett_rsh);

	/* If this packet doesn't end with a null terminated string,
	 * then it must be session data only and we can skip looking
	 * for the other fields.
	 */
	if(tvb_find_guint8(tvb, tvb_length(tvb)-1, 1, '\0') == -1){
		hash_info->state = WAIT_FOR_DATA;
	}

	if(hash_info->state == WAIT_FOR_STDERR_PORT
	&& tvb_length_remaining(tvb, offset)){
		field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length);

		/* Check if this looks like the stderr_port field.
		 * It is optional, so it may only be 1 character long
		 * (the NULL)
		 */
		if(length == 1 || (isdigit_string(field_stringz)
		&& length <= RSH_STDERR_PORT_LEN)){
			proto_tree_add_string(rsh_tree, hf_rsh_stderr_port, tvb, offset, length, (gchar*)field_stringz);
			 /* Next field we need */
			hash_info->state = WAIT_FOR_CLIENT_USERNAME;
		} else {
			/* Since the data doesn't match this field, it must be data only */
			hash_info->state = WAIT_FOR_DATA;
		}

		/* Used if the next field is in the same packet */
		offset += length;
	}


	if(hash_info->state == WAIT_FOR_CLIENT_USERNAME
	&& tvb_length_remaining(tvb, offset)){
		field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length);

		/* Check if this looks like the username field */
		if(length != 1 && length <= RSH_CLIENT_USERNAME_LEN
		&& isprint_string(field_stringz)){
			proto_tree_add_string(rsh_tree, hf_rsh_client_username, tvb, offset, length, (gchar*)field_stringz);

			/* Store the client username so we can display it in the
			 * info column of the entire conversation
			 */
			if(!hash_info->client_username){
				hash_info->client_username=se_strdup((gchar*)field_stringz);
			}

			 /* Next field we need */
			hash_info->state = WAIT_FOR_SERVER_USERNAME;
		} else {
			/* Since the data doesn't match this field, it must be data only */
			hash_info->state = WAIT_FOR_DATA;
		}

		/* Used if the next field is in the same packet */
		offset += length;
	}


	if(hash_info->state == WAIT_FOR_SERVER_USERNAME
	&& tvb_length_remaining(tvb, offset)){
		field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length);

		/* Check if this looks like the password field */
		if(length != 1 && length <= RSH_SERVER_USERNAME_LEN
		&& isprint_string(field_stringz)){
			proto_tree_add_string(rsh_tree, hf_rsh_server_username, tvb, offset, length, (gchar*)field_stringz);

			/* Store the server username so we can display it in the
			 * info column of the entire conversation
			 */
			if(!hash_info->server_username){
				hash_info->server_username=se_strdup((gchar*)field_stringz);
			}

			/* Next field we need */
			hash_info->state = WAIT_FOR_COMMAND;
		} else {
			/* Since the data doesn't match this field, it must be data only */
			hash_info->state = WAIT_FOR_DATA;
		}

		/* Used if the next field is in the same packet */
		offset += length;
		 /* Next field we are looking for */
		hash_info->state = WAIT_FOR_COMMAND;
	}


	if(hash_info->state == WAIT_FOR_COMMAND
	&& tvb_length_remaining(tvb, offset)){
		field_stringz = tvb_get_ephemeral_stringz(tvb, offset, &length);

		/* Check if this looks like the command field */
		if(length != 1 && length <= RSH_COMMAND_LEN
		&& isprint_string(field_stringz)){
			proto_tree_add_string(rsh_tree, hf_rsh_command, tvb, offset, length, (gchar*)field_stringz);

			/* Store the command so we can display it in the
			 * info column of the entire conversation
			 */
			if(!hash_info->command){
				hash_info->command=se_strdup((gchar*)field_stringz);
			}

		} else {
			/* Since the data doesn't match this field, it must be data only */
			hash_info->state = WAIT_FOR_DATA;
		}
	}


	if(hash_info->state == WAIT_FOR_DATA
	&& tvb_length_remaining(tvb, offset)){
		if(pinfo->destport == RSH_PORT){
			/* Packet going to the server */
			/* offset = 0 since the whole packet is data */
			proto_tree_add_text(rsh_tree, tvb, 0, -1, "Client -> Server Data");

			col_append_str(pinfo->cinfo, COL_INFO, "Client -> Server data");
		} else {
			/* This packet must be going back to the client */
			/* offset = 0 since the whole packet is data */
			proto_tree_add_text(rsh_tree, tvb, 0, -1, "Server -> Client Data");

			col_append_str(pinfo->cinfo, COL_INFO, "Server -> Client Data");
		}
	}

	/* We haven't seen all of the fields yet */
	if(hash_info->state < WAIT_FOR_DATA){
		col_set_str(pinfo->cinfo, COL_INFO, "Session Establishment");
	}
}
Exemplo n.º 16
0
static int
dissect_headers(proto_tree *tree, tvbuff_t *tvb, int offset, packet_info *pinfo)
{
    proto_tree *hdrs_tree   = NULL;
    proto_tree *hdr_tree    = NULL;
    proto_item *hdr         = NULL;
    proto_item *handle_item;
    gint        item_length = -1;
    guint8      hdr_id, i;

    if (tvb_length_remaining(tvb, offset) > 0) {
        proto_item *hdrs;
        hdrs      = proto_tree_add_text(tree, tvb, offset, item_length, "Headers");
        hdrs_tree = proto_item_add_subtree(hdrs, ett_btobex_hdrs);
    }
    else {
        return offset;
    }

    while (tvb_length_remaining(tvb, offset) > 0) {
        hdr_id = tvb_get_guint8(tvb, offset);

        switch(0xC0 & hdr_id)
        {
            case 0x00: /* null terminated unicode */
                item_length = tvb_get_ntohs(tvb, offset+1);
                break;
            case 0x40:  /* byte sequence */
                item_length = tvb_get_ntohs(tvb, offset+1);
                break;
            case 0x80:  /* 1 byte */
                item_length = 2;
                break;
            case 0xc0:  /* 4 bytes */
                item_length = 5;
                break;
        }

        hdr = proto_tree_add_text(hdrs_tree, tvb, offset, item_length, "%s",
                                  val_to_str_ext_const(hdr_id, &header_id_vals_ext, "Unknown"));
        hdr_tree = proto_item_add_subtree(hdr, ett_btobex_hdr);

        proto_tree_add_item(hdr_tree, hf_hdr_id, tvb, offset, 1, ENC_BIG_ENDIAN);

        offset++;

        switch(0xC0 & hdr_id)
        {
            case 0x00: /* null terminated unicode */
                {
                    proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN);
                    offset += 2;

                    if ((item_length - 3) > 0) {
                        char *str;

                        display_unicode_string(tvb, hdr_tree, offset, &str);
                        proto_item_append_text(hdr_tree, " (\"%s\")", str);
                        col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", str);
                    }
                    else {
                        col_append_str(pinfo->cinfo, COL_INFO, " \"\"");
                    }

                    offset += item_length - 3;
                }
                break;
            case 0x40:  /* byte sequence */
                proto_tree_add_item(hdr_tree, hf_hdr_length, tvb, offset, 2, ENC_BIG_ENDIAN);
                offset += 2;

                handle_item = proto_tree_add_item(hdr_tree, hf_hdr_val_byte_seq, tvb, offset, item_length - 3, ENC_NA);

                if (((hdr_id == 0x46) || (hdr_id == 0x4a)) && (item_length == 19)) { /* target or who */
                    for(i=0; target_vals[i].strptr != NULL; i++) {
                        if (tvb_memeql(tvb, offset, target_vals[i].value, 16) == 0) {
                            proto_item_append_text(handle_item, ": %s", target_vals[i].strptr);
                            proto_item_append_text(hdr_tree, " (%s)", target_vals[i].strptr);
                            col_append_fstr(pinfo->cinfo, COL_INFO, " - %s", target_vals[i].strptr);
                        }
                    }
                }

                if (!tvb_strneql(tvb, offset, "<?xml", 5))
                {
                    tvbuff_t* next_tvb = tvb_new_subset_remaining(tvb, offset);

                    call_dissector(xml_handle, next_tvb, pinfo, tree);
                }
                else if (is_ascii_str(tvb_get_ptr(tvb, offset,item_length - 3), item_length - 3))
                {
                    proto_item_append_text(hdr_tree, " (\"%s\")", tvb_get_ephemeral_string(tvb, offset,item_length - 3));
                    col_append_fstr(pinfo->cinfo, COL_INFO, " \"%s\"", tvb_get_ephemeral_string(tvb, offset,item_length - 3));
                }

                offset += item_length - 3;
                break;
            case 0x80:  /* 1 byte */
                proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset));
                proto_tree_add_item(hdr_tree, hf_hdr_val_byte, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset++;
                break;
            case 0xc0:  /* 4 bytes */
                proto_item_append_text(hdr_tree, " (%i)", tvb_get_ntohl(tvb, offset));
                proto_tree_add_item(hdr_tree, hf_hdr_val_long, tvb, offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
                break;
            default:
                break;
        }
    }

    return offset;
}
Exemplo n.º 17
0
/****************************************************************
 * Main dissection function
 ****************************************************************/
static void
dissect_rlogin(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	struct tcpinfo *tcpinfo = (struct tcpinfo *)pinfo->private_data;
	conversation_t *conversation;
	rlogin_hash_entry_t *hash_info;
	guint length;
	gint ti_offset;

	/* Get or create conversation */
	conversation = find_or_create_conversation(pinfo);

	/* Get or create data associated with this conversation */
	hash_info = (rlogin_hash_entry_t *)conversation_get_proto_data(conversation, proto_rlogin);
	if (!hash_info)
	{
		/* Populate new data struct... */
		hash_info = wmem_new(wmem_file_scope(), rlogin_hash_entry_t);
		hash_info->state = NONE;
		hash_info->info_framenum = 0;  /* no frame has the number 0 */
		hash_info->user_name[0] = '\0';

		/* ... and store in conversation */
		conversation_add_proto_data(conversation, proto_rlogin, hash_info);
	}

	/* Set protocol column text */
	col_set_str(pinfo->cinfo, COL_PROTOCOL, "Rlogin");

	/* Set info column */
	/* Show user-name if available */
	if (hash_info->user_name[0])
	{
		col_add_fstr(pinfo->cinfo, COL_INFO,
		              "User name: %s, ", hash_info->user_name);
	}
	else
	{
		col_clear(pinfo->cinfo, COL_INFO);
	}

	/* Work out packet content summary for display */
	length = tvb_length(tvb);
	if (length != 0)
	{
		/* Initial NULL byte represents part of connection handshake */
		if (tvb_get_guint8(tvb, 0) == '\0')
		{
			col_append_str(pinfo->cinfo, COL_INFO,
				               (pinfo->destport == RLOGIN_PORT) ?
				                   "Start Handshake" :
				                   "Startup info received");
		}
		else
		if (tcpinfo->urgent && length >= tcpinfo->urgent_pointer)
		{
			/* Urgent pointer inside current data represents a control message */
			col_append_str(pinfo->cinfo, COL_INFO, "Control Message");
		}
		else
		{
			/* Search for 2 consecutive ff bytes
			  (signifies window change control message) */
			ti_offset = tvb_find_guint8(tvb, 0, -1, 0xff);
			if (ti_offset != -1 &&
			    tvb_bytes_exist(tvb, ti_offset + 1, 1) &&
			    tvb_get_guint8(tvb, ti_offset + 1) == 0xff)
			{
				col_append_str(pinfo->cinfo, COL_INFO, "Terminal Info");
			}
			else
			{
				/* Show any text data in the frame */
				int bytes_to_copy = tvb_length(tvb);
				if (bytes_to_copy > 128)
				{
					/* Truncate to 128 bytes for display */
					bytes_to_copy = 128;
				}

				/* Add data into info column */
				col_append_fstr(pinfo->cinfo, COL_INFO,
				                "Data: %s",
				                 tvb_format_text(tvb, 0, bytes_to_copy));
			}
		}
	}

	/* See if conversation state needs to be updated */
	rlogin_state_machine(hash_info, tvb, pinfo);

	/* Dissect in detail */
	rlogin_display(hash_info, tvb, pinfo, tree, tcpinfo);
}
Exemplo n.º 18
0
static int
dissect_PNMRP_PDU(tvbuff_t *tvb, int offset, 
	packet_info *pinfo, proto_tree *tree, proto_item *item)
{
    guint16 version;
    guint8 type;
    guint8 length;
    gint i;
    tvbuff_t *new_tvb;


    /* MRP_Version */
    offset = dissect_pn_uint16(tvb, offset, pinfo, tree, hf_pn_mrp_version, &version);

    /* the rest of the packet has 4byte alignment regarding to the beginning of the next TLV block! */
    /* XXX - do we have to free this new tvb below? */
    new_tvb = tvb_new_subset_remaining(tvb, offset);
    offset = 0;

    for(i=0; tvb_length_remaining(tvb, offset) > 0; i++) {
        /* MRP_TLVHeader.Type */
        offset = dissect_pn_uint8(new_tvb, offset, pinfo, tree, hf_pn_mrp_type, &type);

        /* MRP_TLVHeader.Length */
        offset = dissect_pn_uint8(new_tvb, offset, pinfo, tree, hf_pn_mrp_length, &length);

        if(i != 0) {
            col_append_str(pinfo->cinfo, COL_INFO, ", ");

            proto_item_append_text(item, ", ");
        }

        switch(type) {
        case(0x00):
            /* no content */
            col_append_str(pinfo->cinfo, COL_INFO, "End");
            proto_item_append_text(item, "End");
            return offset;
            break;
        case(0x01):
            offset = dissect_PNMRP_Common(new_tvb, offset, pinfo, tree, item);
            break;
        case(0x02):
            offset = dissect_PNMRP_Test(new_tvb, offset, pinfo, tree, item);
            break;
        case(0x03):
            offset = dissect_PNMRP_TopologyChange(new_tvb, offset, pinfo, tree, item);
            break;
        case(0x04):
            offset = dissect_PNMRP_LinkDown(new_tvb, offset, pinfo, tree, item);
            break;
        case(0x05):
            offset = dissect_PNMRP_LinkUp(new_tvb, offset, pinfo, tree, item);
            break;
        case(0x7f):
            offset = dissect_PNMRP_Option(new_tvb, offset, pinfo, tree, item, length);
            break;
        default:
            offset = dissect_pn_undecoded(tvb, offset, pinfo, tree, length);

 		col_append_fstr(pinfo->cinfo, COL_INFO, "Unknown TLVType 0x%x", type);
	    proto_item_append_text(item, "Unknown TLVType 0x%x", type);
        }
    }

    return offset;
}
Exemplo n.º 19
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;
    }
}
Exemplo n.º 20
0
static void _dissect_uasip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, e_ua_direction direction)
{
    proto_item *uasip_item;
    proto_tree *uasip_tree;
    guint8      opcode;
    gint        offset = 0;

    if (noesip_enabled)
    {
        col_append_str(pinfo->cinfo, COL_PROTOCOL, "/NOE");
    }
    else
    {
        col_append_str(pinfo->cinfo, COL_PROTOCOL, "/DL");
    }

    opcode = tvb_get_guint8(tvb, offset);
    offset++;

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

    col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str_ext(opcode, &uaudp_opcode_str_ext, "unknown (0x%02x)"));

    uasip_item = proto_tree_add_protocol_format(tree, proto_uasip, tvb, 0, 5,
                                                "SIP/NOE Protocol, %s",
                                                val_to_str_ext(opcode, &uaudp_opcode_str_ext, "unknown (0x%02x)"));
    uasip_tree = proto_item_add_subtree(uasip_item, ett_uasip);
    proto_tree_add_uint(uasip_tree, hf_uasip_opcode, tvb, 0, 1, opcode);

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

                switch(T)
                {
                    case UAUDP_CONNECT_VERSION:
                        rTLV(uasip_tree, &hf_uasip_version, tvb, offset, L);
                    break;

                    case UAUDP_CONNECT_WINDOW_SIZE:
                        rTLV(uasip_tree, &hf_uasip_window_size, tvb, offset, L);
                    break;

                    case UAUDP_CONNECT_MTU:
                        rTLV(uasip_tree, &hf_uasip_mtu, tvb, offset, L);
                    break;

                    case UAUDP_CONNECT_UDP_LOST:
                        rTLV(uasip_tree, &hf_uasip_udp_lost, tvb, offset, L);
                    break;

                    case UAUDP_CONNECT_UDP_LOST_REINIT:
                        rTLV(uasip_tree, &hf_uasip_udp_lost_reinit, tvb, offset, L);
                    break;

                    case UAUDP_CONNECT_KEEPALIVE:
                        rTLV(uasip_tree, &hf_uasip_keepalive, tvb, offset, L);
                    break;

                    case UAUDP_CONNECT_QOS_IP_TOS:
                        rTLV(uasip_tree, &hf_uasip_qos_ip_tos, tvb, offset, L);
                    break;

                    case UAUDP_CONNECT_QOS_8021_VLID:
                        rTLV(uasip_tree, &hf_uasip_qos_8021_vlid, tvb, offset, L);
                    break;

                    case UAUDP_CONNECT_QOS_8021_PRI:
                        rTLV(uasip_tree, &hf_uasip_qos_8021_pri, tvb, offset, L);
                    break;

                    default:
                    break;
                }
                offset += (2 + L);
            }
        }
        break;

        case UAUDP_NACK:
        {
            proto_tree_add_uint(uasip_tree, hf_uasip_expseq, tvb, offset, 2, tvb_get_ntohs(tvb, offset));
            ua_tap_info.expseq = tvb_get_ntohs(tvb, offset+0);

            /*offset += 2;*/

            if (noesip_enabled)
            {
                col_add_fstr(pinfo->cinfo, COL_INFO, "NACK");
            }
            else
            {
                col_add_fstr(pinfo->cinfo, COL_INFO, "NACK exp:%d", ua_tap_info.expseq);
            }
        }
        break;

        case UAUDP_DATA:
        {
            int datalen;

            proto_tree_add_uint(uasip_tree, hf_uasip_expseq, tvb, offset+0, 2, tvb_get_ntohs(tvb, offset+0));
            proto_tree_add_uint(uasip_tree, hf_uasip_sntseq, tvb, offset+2, 2, tvb_get_ntohs(tvb, offset+2));
            ua_tap_info.expseq = tvb_get_ntohs(tvb, offset+0);
            ua_tap_info.sntseq = tvb_get_ntohs(tvb, offset+2);
            offset += 4;
            datalen  = (tvb_length(tvb) - offset);

            if (noesip_enabled)
            {
                if (datalen > 0)
                {
                    if (direction == SYS_TO_TERM)
                    {
                        call_dissector(ua_sys_to_term_handle, tvb_new_subset(tvb, offset, datalen, datalen), pinfo, tree);
                    }
                    else if (direction == TERM_TO_SYS)
                    {
                        call_dissector(ua_term_to_sys_handle, tvb_new_subset(tvb, offset, datalen, datalen), pinfo, tree);
                    }
                    else
                    {
                        col_add_str(pinfo->cinfo, COL_INFO, "DATA - Couldn't resolve direction.");
                    }
                }
                else
                {
                    col_add_str(pinfo->cinfo, COL_INFO, "ACK");
                }
            }
            else
            {
                if (datalen > 0)
                {
                    col_add_fstr(pinfo->cinfo, COL_INFO, "DATA exp:%d", ua_tap_info.expseq);
                    col_append_fstr(pinfo->cinfo, COL_INFO, " snt:%d", ua_tap_info.sntseq);
                }
                else
                {
                    col_add_fstr(pinfo->cinfo, COL_INFO, "ACK  exp:%d", ua_tap_info.expseq);
                    col_append_fstr(pinfo->cinfo, COL_INFO, " snt:%d", ua_tap_info.sntseq);
                }
            }
        }
        break;

        default:
        break;
    }
#if 0
    tap_queue_packet(uasip_tap, pinfo, &ua_tap_info);
#endif
}
Exemplo n.º 21
0
static void
dissect_status (packet_info *pinfo, proto_tree *parent_tree, tvbuff_t *tvb, int offset, guint8 flags)
{
    proto_item *item = NULL;
    proto_tree *tree = NULL;

    if (parent_tree) {
        item=proto_tree_add_uint(parent_tree, hf_sbccs_dib_status,
                                 tvb, offset, 1, flags);
        tree=proto_item_add_subtree(item, ett_sbccs_dib_status);
    }


    proto_tree_add_boolean(tree, hf_sbccs_dib_status_attention, tvb, offset, 1, flags);
    if (flags & 0x80) {
        proto_item_append_text(item, "  Attention");
        col_append_str(pinfo->cinfo, COL_INFO, "  Attention");
    }
    flags &= (~( 0x80 ));

    proto_tree_add_boolean(tree, hf_sbccs_dib_status_modifier, tvb, offset, 1, flags);
    if (flags & 0x40) {
        proto_item_append_text(item, "  Status Modifier");
        col_append_str(pinfo->cinfo, COL_INFO, "  Status Modifier");
    }
    flags &= (~( 0x40 ));

    proto_tree_add_boolean(tree, hf_sbccs_dib_status_cue, tvb, offset, 1, flags);
    if (flags & 0x20) {
        proto_item_append_text(item, "  Control-Unit End");
        col_append_str(pinfo->cinfo, COL_INFO, "  Control-Unit End");
    }
    flags &= (~( 0x20 ));

    proto_tree_add_boolean(tree, hf_sbccs_dib_status_busy, tvb, offset, 1, flags);
    if (flags & 0x10) {
        proto_item_append_text(item, "  Busy");
        col_append_str(pinfo->cinfo, COL_INFO, "  Busy");
    }
    flags &= (~( 0x10 ));

    proto_tree_add_boolean(tree, hf_sbccs_dib_status_channelend, tvb, offset, 1, flags);
    if (flags & 0x08) {
        proto_item_append_text(item, "  Channel End");
        col_append_str(pinfo->cinfo, COL_INFO, "  Channel End");
    }
    flags &= (~( 0x08 ));

    proto_tree_add_boolean(tree, hf_sbccs_dib_status_deviceend, tvb, offset, 1, flags);
    if (flags & 0x04) {
        proto_item_append_text(item, "  Device End");
        col_append_str(pinfo->cinfo, COL_INFO, "  Device End");
    }
    flags &= (~( 0x04 ));

    proto_tree_add_boolean(tree, hf_sbccs_dib_status_unit_check, tvb, offset, 1, flags);
    if (flags & 0x02) {
        proto_item_append_text(item, "  Unit Check");
        col_append_str(pinfo->cinfo, COL_INFO, "  Unit Check");
    }
    flags &= (~( 0x02 ));

    proto_tree_add_boolean(tree, hf_sbccs_dib_status_unit_exception, tvb, offset, 1, flags);
    if (flags & 0x01) {
        proto_item_append_text(item, "  Unit Exception");
        col_append_str(pinfo->cinfo, COL_INFO, "  Unit Exception");
    }
    /*flags &= (~( 0x01 ));*/

}
Exemplo n.º 22
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;
}
Exemplo n.º 23
0
/* dissect a response. more work to do here.
 */
static void
display_rsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ajp13_tree, ajp13_conv_data* cd)
{
  int pos = 0;
  guint8 mcode = 0;
  int i;

  /* MAGIC
   */
  if (ajp13_tree)
    proto_tree_add_item(ajp13_tree, hf_ajp13_magic, tvb, pos, 2, ENC_NA);
  pos+=2;

  /* PDU LENGTH
   */
  if (ajp13_tree)
    proto_tree_add_item(ajp13_tree, hf_ajp13_len,   tvb, pos, 2, ENC_BIG_ENDIAN);
  pos+=2;

  /* MESSAGE TYPE CODE
   */
  mcode = tvb_get_guint8(tvb, pos);
  col_append_str(pinfo->cinfo, COL_INFO, val_to_str(mcode, mtype_codes, "Unknown message code %u"));
  if (ajp13_tree)
    proto_tree_add_item(ajp13_tree, hf_ajp13_code, tvb, pos, 1, ENC_BIG_ENDIAN);
  pos+=1;

  switch (mcode) {

  case MTYPE_END_RESPONSE:
    if (ajp13_tree)
      proto_tree_add_item(ajp13_tree, hf_ajp13_reusep, tvb, pos, 1, ENC_BIG_ENDIAN);
    /*pos+=1;*/
    break;

  case MTYPE_SEND_HEADERS:
  {
    const gchar *rsmsg;
    guint16 rsmsg_len;
    guint16 nhdr;
    guint16 rcode_num;

    /* HTTP RESPONSE STATUS CODE
     */
    rcode_num = tvb_get_ntohs(tvb, pos);
    col_append_fstr(pinfo->cinfo, COL_INFO, ":%d", rcode_num);
    if (ajp13_tree)
      proto_tree_add_item(ajp13_tree, hf_ajp13_rstatus, tvb, pos, 2, ENC_BIG_ENDIAN);
    pos+=2;

    /* HTTP RESPONSE STATUS MESSAGE
     */
    rsmsg = ajp13_get_nstring(tvb, pos, &rsmsg_len);
    col_append_fstr(pinfo->cinfo, COL_INFO, " %s", rsmsg);
    if (ajp13_tree)
      proto_tree_add_string(ajp13_tree, hf_ajp13_rsmsg, tvb, pos, rsmsg_len+2, rsmsg);
    pos+=rsmsg_len+2;

    /* NUMBER OF HEADERS
     */
    nhdr = tvb_get_ntohs(tvb, pos);
    if (ajp13_tree)
      proto_tree_add_item(ajp13_tree, hf_ajp13_nhdr, tvb, pos, 2, ENC_BIG_ENDIAN);
    pos+=2;

    /* HEADERS
     */
    for(i=0; i<nhdr; i++) {

      guint8 hcd;
      guint8 hid;
      const gchar *hval;
      guint16 hval_len, hname_len;
      const gchar* hname = NULL;
      int hpos = pos;
      /* int cl = 0; TODO: Content-Length header (encoded by 0x08) is special */

      /* HEADER CODE/NAME
       */
      hcd = tvb_get_guint8(tvb, pos);

      if (hcd == 0xA0) {
        pos+=1;
        hid = tvb_get_guint8(tvb, pos);
        pos+=1;

        if (hid >= array_length(rsp_headers))
          hid = 0;

        hval = ajp13_get_nstring(tvb, pos, &hval_len);

        proto_tree_add_string_format_value(ajp13_tree, *rsp_headers[hid],
                                       tvb, hpos, 2+hval_len+2, hval,
                                       "%s", hval);
        pos+=hval_len+2;
#if 0
        /* TODO: Content-Length header (encoded by 0x08) is special */
        if (hid == 0x08)
          cl = 1;
#endif
      } else {
        hname = ajp13_get_nstring(tvb, pos, &hname_len);
        pos+=hname_len+2;

        hval = ajp13_get_nstring(tvb, pos, &hval_len);

        proto_tree_add_string_format(ajp13_tree, hf_ajp13_additional_header,
                                tvb, hpos, hname_len+2+hval_len+2,
                                wmem_strdup_printf(wmem_packet_scope(), "%s: %s", hname, hval),
                                "%s: %s", hname, hval);
        pos+=hval_len+2;
      }
    }
    break;
  }

  case MTYPE_GET_BODY_CHUNK:
  {
    guint16 rlen;
    rlen = tvb_get_ntohs(tvb, pos);
    cd->content_length = rlen;
    if (ajp13_tree)
      proto_tree_add_item(ajp13_tree, hf_ajp13_rlen, tvb, pos, 2, ENC_BIG_ENDIAN);
    /*pos+=2;*/
    break;
  }

  case MTYPE_CPONG:
    break;

  default:
    /* MESSAGE DATA (COPOUT)
     */
    if (ajp13_tree)
      proto_tree_add_item(ajp13_tree, hf_ajp13_data,  tvb, pos+2, -1, ENC_UTF_8|ENC_NA);
    break;
  }
}
Exemplo n.º 24
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;
}
Exemplo n.º 25
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);
        }
}
Exemplo n.º 26
0
/* Code to actually dissect the packets
*/
static void
dissect_sndcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint8         addr_field, comp_field, npdu_field1, nsapi, dcomp=0, pcomp=0;
  guint16        offset=0, npdu=0, segment=0, npdu_field2;
  tvbuff_t      *next_tvb, *npdu_tvb;
  gint           len;
  gboolean       first, more_frags, unack;

  /* Set up structures needed to add the protocol subtree and manage it
   */
  proto_item *ti, *address_field_item, *compression_field_item, *npdu_field_item;
  proto_tree *sndcp_tree = NULL, *address_field_tree, *compression_field_tree, *npdu_field_tree;

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

  /* create display subtree for the protocol
   */
  if (tree) {
    ti         = proto_tree_add_item(tree, proto_sndcp, tvb, 0, -1, ENC_NA);
    sndcp_tree = proto_item_add_subtree(ti, ett_sndcp);
  }

  /* get address field from next byte
   */
  addr_field = tvb_get_guint8(tvb,offset);
  nsapi      = addr_field & 0xF;
  first      = addr_field & MASK_F;
  more_frags = addr_field & MASK_M;
  unack      = addr_field & MASK_T;

  /* add subtree for the address field
   */
  if (tree) {
    address_field_item = proto_tree_add_uint_format(sndcp_tree,hf_sndcp_nsapi,
                                                    tvb, offset,1, nsapi,
                                                    "Address field  NSAPI: %d", nsapi );
    address_field_tree = proto_item_add_subtree(address_field_item, ett_sndcp_address_field);
    proto_tree_add_boolean(address_field_tree, hf_sndcp_x, tvb,offset,1, addr_field );
    proto_tree_add_boolean(address_field_tree, hf_sndcp_f, tvb,offset,1, addr_field );
    proto_tree_add_boolean(address_field_tree, hf_sndcp_t, tvb,offset,1, addr_field );
    proto_tree_add_boolean(address_field_tree, hf_sndcp_m, tvb,offset,1, addr_field );
    proto_tree_add_uint(address_field_tree, hf_sndcp_nsapib, tvb, offset, 1, addr_field );
  }
  offset++;

  /* get compression pointers from next byte if this is the first segment
   */
  if (first) {
    comp_field = tvb_get_guint8(tvb,offset);
    dcomp      = comp_field & 0xF0;
    pcomp      = comp_field & 0x0F;

    /* add subtree for the compression field
     */
    if (tree) {
      if (!pcomp) {
        if (!dcomp) {
          compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "No compression");
        }
        else {
          compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Data compression");
        }
      }
      else {
        if (!dcomp) {
          compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Protocol compression");
        }
        else {
          compression_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Data and Protocol compression");
        }
      }
      compression_field_tree = proto_item_add_subtree(compression_field_item, ett_sndcp_compression_field);
      proto_tree_add_uint(compression_field_tree, hf_sndcp_dcomp, tvb, offset, 1, comp_field );
      proto_tree_add_uint(compression_field_tree, hf_sndcp_pcomp, tvb, offset, 1, comp_field );
    }
    offset++;

    /* get N-PDU number from next byte for acknowledged mode (only for first segment)
     */
    if (!unack) {
      npdu = npdu_field1 = tvb_get_guint8(tvb,offset);
      col_add_fstr(pinfo->cinfo, COL_INFO, "SN-DATA N-PDU %d", npdu_field1);
      if (tree) {
        npdu_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,1, "Acknowledged mode, N-PDU %d", npdu_field1 );
        npdu_field_tree = proto_item_add_subtree(npdu_field_item, ett_sndcp_npdu_field);
        proto_tree_add_uint(npdu_field_tree, hf_sndcp_npdu1, tvb, offset, 1, npdu_field1 );
      }
      offset++;
    }
  }

  /* get segment and N-PDU number from next two bytes for unacknowledged mode
   */
  if (unack) {
    npdu_field2     = tvb_get_ntohs(tvb, offset);
    segment         = (npdu_field2 & 0xF000) >> 12;
    npdu            = (npdu_field2 & 0x0FFF);
    col_add_fstr(pinfo->cinfo, COL_INFO, "SN-UNITDATA N-PDU %d (segment %d)", npdu, segment);
    if (tree) {
      npdu_field_item = proto_tree_add_text(sndcp_tree, tvb, offset,2, "Unacknowledged mode, N-PDU %d (segment %d)", npdu, segment );
      npdu_field_tree = proto_item_add_subtree(npdu_field_item, ett_sndcp_npdu_field);
      proto_tree_add_uint(npdu_field_tree, hf_sndcp_segment, tvb, offset, 2, npdu_field2 );
      proto_tree_add_uint(npdu_field_tree, hf_sndcp_npdu2, tvb, offset, 2, npdu_field2 );
    }
    offset         += 2;
  }

  /* handle N-PDU data, reassemble if necessary
   */
  if (first && !more_frags) {
    next_tvb = tvb_new_subset_remaining (tvb, offset);

    if (!dcomp && !pcomp) {
      call_dissector(ip_handle, next_tvb, pinfo, tree);
    }
    else {
      call_dissector(data_handle, next_tvb, pinfo, tree);
    }
  }
  else {
    /* Try reassembling fragments
     */
    fragment_head  *fd_npdu         = NULL;
    guint32         reassembled_in  = 0;
    gboolean        save_fragmented = pinfo->fragmented;

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

    pinfo->fragmented = TRUE;

    if (unack)
      fd_npdu  = fragment_add_seq_check(&npdu_reassembly_table, tvb, offset,
                                        pinfo, npdu, NULL, segment, len, more_frags);
    else
      fd_npdu  = fragment_add(&npdu_reassembly_table, tvb, offset, pinfo, npdu, NULL,
                              offset, len, more_frags);

    npdu_tvb = process_reassembled_data(tvb, offset, pinfo,
                                        "Reassembled N-PDU", fd_npdu, &npdu_frag_items,
                                        NULL, sndcp_tree);
    if (fd_npdu) {
      /* Reassembled
       */
      reassembled_in = fd_npdu->reassembled_in;
      if (pinfo->fd->num == reassembled_in) {
        /* Reassembled in this very packet:
         * We can safely hand the tvb to the IP dissector
         */
        call_dissector(ip_handle, npdu_tvb, pinfo, tree);
      }
      else {
        /* Not reassembled in this packet
         */
        col_append_fstr(pinfo->cinfo, COL_INFO,
                          " (N-PDU payload reassembled in packet %u)",
                          fd_npdu->reassembled_in);
        if (tree) {
          proto_tree_add_text(sndcp_tree, tvb, offset, -1, "Payload");
        }
      }
    } else {
      /* Not reassembled yet, or not reassembled at all
       */
      if (unack)
        col_append_fstr(pinfo->cinfo, COL_INFO, " (Unreassembled fragment %u)", segment);
      else
        col_append_str(pinfo->cinfo, COL_INFO, " (Unreassembled fragment)");

      if (tree) {
        proto_tree_add_text(sndcp_tree, tvb, offset, -1, "Payload");
      }
    }
    /* Now reset fragmentation information in pinfo
     */
    pinfo->fragmented = save_fragmented;
  }
}
Exemplo n.º 27
0
static void
dissect_rtp_events( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree )
{
	proto_item   *ti;
	proto_tree   *rtp_events_tree;
	unsigned int  offset = 0;

	struct _rtp_conversation_info *p_conv_data;

	guint8 rtp_evt;
	guint8 octet;

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


	/* Get event fields */

	rtp_evt = tvb_get_guint8(tvb, offset );

	/* get tap info */
	rtp_event_info.info_rtp_evt = rtp_evt;

	p_conv_data = (struct _rtp_conversation_info *)p_get_proto_data(wmem_file_scope(), pinfo, proto_get_id_by_filter_name("rtp"), 0);
	if (p_conv_data)
		rtp_event_info.info_setup_frame_num = p_conv_data->frame_number;
	else
		rtp_event_info.info_setup_frame_num = 0;


	col_add_fstr( pinfo->cinfo, COL_INFO,
		"Payload type=RTP Event, %s",
		val_to_str_ext( rtp_evt, &rtp_event_type_values_ext, "Unknown (%u)" ));

	ti = proto_tree_add_item( tree, proto_rtp_events, tvb, offset, -1, ENC_NA );
	rtp_events_tree = proto_item_add_subtree( ti, ett_rtp_events );

	proto_tree_add_uint ( rtp_events_tree, hf_rtp_events_event, tvb, offset, 1, rtp_evt);
	offset++;
	octet = tvb_get_guint8(tvb, offset);
	proto_tree_add_boolean (rtp_events_tree, hf_rtp_events_end, tvb, offset, 1, octet);
	proto_tree_add_boolean (rtp_events_tree, hf_rtp_events_reserved, tvb, offset, 1, octet);
	proto_tree_add_uint ( rtp_events_tree, hf_rtp_events_volume, tvb, offset, 1, octet);
	offset++;

	/* The duration field indicates the duration of the event or segment
	 * being reported, in timestamp units.
	 */
	rtp_event_info.info_duration = tvb_get_ntohs(tvb, offset);
	proto_tree_add_item ( rtp_events_tree, hf_rtp_events_duration, tvb, offset, 2, ENC_BIG_ENDIAN);

	/* set the end info for the tap */
	if (octet & 0x80)
	{
		rtp_event_info.info_end = TRUE;
	} else
	{
		rtp_event_info.info_end = FALSE;
	}

	/* Make end-of-event packets obvious in the info column */
	if ((octet & 0x80))
	{
		col_append_str(pinfo->cinfo, COL_INFO, " (end)");
	}

	tap_queue_packet(rtp_event_tap, pinfo, &rtp_event_info);
}
static void
dissect_gsm_cell_broadcast(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
   guint8 sms_encoding, total_pages, current_page;
   guint32       offset = 0;
   guint         len, text_len;
   guint32       msg_key;
   proto_item    *cbs_page_item = NULL;
   proto_tree    *cbs_page_tree = NULL;
   guint16       serial_number, message_id;
   tvbuff_t      *cbs_page_tvb = NULL;
   tvbuff_t      *cbs_msg_tvb = NULL;
   fragment_head * frag_data = NULL;

   len = tvb_length(tvb);

   col_append_str(pinfo->cinfo, COL_PROTOCOL, " Cell Broadcast");
   col_append_str(pinfo->cinfo, COL_INFO, " (CBS Page)");

   cbs_page_item = proto_tree_add_protocol_format(proto_tree_get_root(tree), proto_cell_broadcast, tvb, 0, len, "GSM Cell Broadcast");
   cbs_page_tree = proto_item_add_subtree(cbs_page_item, ett_gsm_cbs_page);

   serial_number = tvb_get_ntohs(tvb, offset);
   offset += dissect_cbs_serial_number(tvb, cbs_page_tree, offset);
   message_id = tvb_get_ntohs(tvb, offset);
   offset += dissect_cbs_message_identifier(tvb, cbs_page_tree, offset);
   sms_encoding = dissect_cbs_data_coding_scheme(tvb, pinfo, cbs_page_tree, offset++);
   total_pages = tvb_get_guint8(tvb, offset);
   current_page = (total_pages & 0xF0) >> 4;
   total_pages &= 0x0F;
   proto_tree_add_item(cbs_page_tree, hf_gsm_cbs_current_page, tvb, offset, 1, ENC_BIG_ENDIAN);
   proto_tree_add_item(cbs_page_tree, hf_gsm_cbs_total_pages, tvb, offset++, 1, ENC_BIG_ENDIAN);
   cbs_page_tvb = dissect_cbs_data(sms_encoding, tvb, cbs_page_tree, pinfo, offset );

   if (cbs_page_tvb != NULL)
   {
      text_len = tvb_length(cbs_page_tvb);
      while (text_len && (tvb_get_guint8(cbs_page_tvb, text_len-1) == '\r')) {
         text_len--;
      }
      if (tree != NULL)
      {
         proto_item *item = proto_tree_add_text(cbs_page_tree, tvb, offset, -1, "Cell Broadcast Page Contents");
         proto_tree *cbs_page_subtree = proto_item_add_subtree(item, ett_gsm_cbs_page_content);
         len = tvb_length(cbs_page_tvb);
         proto_tree_add_string(cbs_page_subtree, hf_gsm_cbs_page_content, cbs_page_tvb, 0,
                               text_len, tvb_get_string(wmem_packet_scope(), cbs_page_tvb, 0, text_len));
         len -= text_len;
         if (len)
         {
            proto_tree_add_string(cbs_page_subtree, hf_gsm_cbs_page_content_padding, cbs_page_tvb, text_len, len,
                                  tvb_get_string(wmem_packet_scope(), cbs_page_tvb, text_len, len));
         }
      }
      if (text_len)
      {
         cbs_page_tvb = tvb_new_subset(cbs_page_tvb, 0, text_len, text_len);
         if (total_pages == 1)
         {
            /* no need for reassembly */
            cbs_msg_tvb = cbs_page_tvb;
         }
         else
         {
             /* now we have a complete page, try to concatenate the full message */
            /* we can use the serial number and message ID as keys, as they are the same for all pages of a message */
            msg_key = (serial_number << 16) + message_id;
            frag_data = fragment_add_seq_check(&gsm_cbs_reassembly_table,
                                               cbs_page_tvb, 0, pinfo, msg_key, NULL,
                                               (current_page -1), text_len,
                                               (current_page!=total_pages));
            cbs_msg_tvb = process_reassembled_data(cbs_page_tvb, 0, pinfo, "Reassembled Cell Broadcast message",
                                                frag_data, &gsm_page_items, NULL, cbs_page_tree);
         }
      }
   }
   if (cbs_msg_tvb != NULL)
   {
      proto_item     *cbs_msg_item = NULL;
      proto_tree    *cbs_msg_tree = NULL;

      len = tvb_length(cbs_msg_tvb);
      col_append_str(pinfo->cinfo, COL_INFO, " (CBS Message)");

      cbs_msg_item = proto_tree_add_protocol_format(proto_tree_get_root(tree), proto_cell_broadcast, cbs_msg_tvb, 0, len, "GSM Cell Broadcast Message");
      cbs_msg_tree = proto_item_add_subtree(cbs_msg_item, ett_cbs_msg);

      proto_tree_add_string(cbs_msg_tree, hf_gsm_cbs_message_content, cbs_msg_tvb, 0, len, tvb_get_string(wmem_packet_scope(), cbs_msg_tvb, 0, len));
   }
}
Exemplo n.º 29
0
static gint
dissect_hci_usb(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
    proto_item     *ttree = NULL;
    proto_tree     *titem = NULL;
    proto_item     *pitem = NULL;
    gint            offset = 0;
    usb_conv_info_t *usb_conv_info;
    tvbuff_t       *next_tvb = NULL;
    hci_data_t     *hci_data;
    gint            p2p_dir_save;
    guint32         session_id;
    fragment_head  *reassembled;

    /* Reject the packet if data is NULL */
    if (data == NULL)
        return 0;
    usb_conv_info = (usb_conv_info_t *)data;

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

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

    p2p_dir_save = pinfo->p2p_dir;
    pinfo->p2p_dir = (usb_conv_info->is_request) ? P2P_DIR_SENT : P2P_DIR_RECV;

    switch (pinfo->p2p_dir) {

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

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

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

    if (usb_conv_info->is_setup) {
        proto_tree_add_item(ttree, hf_bthci_usb_setup_request, tvb, offset, 1, ENC_LITTLE_ENDIAN);
        offset += 1;

        proto_tree_add_item(ttree, hf_bthci_usb_setup_value, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;

        proto_tree_add_item(ttree, hf_bthci_usb_setup_adapter_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;

        proto_tree_add_item(ttree, hf_bthci_usb_setup_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;
    }

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

    hci_data = (hci_data_t *) wmem_new(wmem_packet_scope(), hci_data_t);

    if (usb_conv_info->device_protocol == 0xE00104)
        hci_data->interface_id = HCI_INTERFACE_AMP;
    else
        hci_data->interface_id = HCI_INTERFACE_USB;

    hci_data->adapter_id = usb_conv_info->bus_id << 8 | usb_conv_info->device_address;
    hci_data->chandle_to_bdaddr_table = chandle_to_bdaddr_table;
    hci_data->bdaddr_to_name_table = bdaddr_to_name_table;
    hci_data->localhost_bdaddr = localhost_bdaddr;
    hci_data->localhost_name = localhost_name;

    pinfo->ptype = PT_BLUETOOTH;

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

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

            wmem_tree_insert32(fragment_info_table, session_id, fragment_info);
        }

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

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

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

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

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

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

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

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

    offset += tvb_length_remaining(tvb, offset);

    pinfo->p2p_dir = p2p_dir_save;

    return offset;
}
Exemplo n.º 30
0
/* Code to actually dissect the packets */
static void
dissect_lsc_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_item *ti;
  proto_tree *lsc_tree;
  guint8 op_code;
  guint32 stream;
  guint expected_len;

  /* Protocol is LSC, packet summary is not yet known */
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "LSC");
  col_clear(pinfo->cinfo, COL_INFO);

  /* Too little data? */
  if (tvb_length(tvb) < LSC_MIN_LEN)
  {
    col_set_str(pinfo->cinfo, COL_INFO, "[Too short]");
    return;
  }

  /* Get the op code */
  op_code = tvb_get_guint8(tvb, 2);
  /* And the stream handle */
  stream = tvb_get_ntohl(tvb, 4);

  /* Check the data length against what we actually received */
  switch (op_code)
    {
      case LSC_PAUSE:
        expected_len = LSC_PAUSE_LEN;
        break;
      case LSC_RESUME:
        expected_len = LSC_RESUME_LEN;
        break;
      case LSC_STATUS:
        expected_len = LSC_STATUS_LEN;
        break;
      case LSC_RESET:
        expected_len = LSC_RESET_LEN;
        break;
      case LSC_JUMP:
        expected_len = LSC_JUMP_LEN;
        break;
      case LSC_PLAY:
        expected_len = LSC_PLAY_LEN;
        break;
      case LSC_DONE:
      case LSC_PAUSE_REPLY:
      case LSC_RESUME_REPLY:
      case LSC_STATUS_REPLY:
      case LSC_RESET_REPLY:
      case LSC_JUMP_REPLY:
      case LSC_PLAY_REPLY:
        expected_len = LSC_REPLY_LEN;
        break;
      default:
        /* Unrecognized op code */
        expected_len = LSC_MIN_LEN;
        break;
    }

  /* Display the op code in the summary */
  if (check_col(pinfo->cinfo, COL_INFO)) {
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s, session %.8u",
                 val_to_str(op_code, op_code_vals, "Unknown op code (0x%x)"),
                 stream);

    if (tvb_length(tvb) < expected_len)
      col_append_str(pinfo->cinfo, COL_INFO, " [Too short]");
    else if (tvb_length(tvb) > expected_len)
      col_append_str(pinfo->cinfo, COL_INFO, " [Too long]");
  }

  if (tree) {
    /* Create display subtree for the protocol */
    ti = proto_tree_add_item(tree, proto_lsc, tvb, 0, -1, ENC_NA);
    lsc_tree = proto_item_add_subtree(ti, ett_lsc);

    /* Add already fetched items to the tree */
    proto_tree_add_uint(lsc_tree, hf_lsc_op_code, tvb, 2, 1, op_code);
    proto_tree_add_uint_format_value(lsc_tree, hf_lsc_stream_handle, tvb, 4, 4,
                                     stream, "%.8u", stream);

    /* Add rest of LSC header */
    proto_tree_add_uint(lsc_tree, hf_lsc_version, tvb, 0, 1,
                        tvb_get_guint8(tvb, 0));
    proto_tree_add_uint(lsc_tree, hf_lsc_trans_id, tvb, 1, 1,
                        tvb_get_guint8(tvb, 1));

    /* Only replies contain a status code */
    if (isReply(op_code))
      proto_tree_add_uint(lsc_tree, hf_lsc_status_code, tvb, 3, 1,
                          tvb_get_guint8(tvb, 3));

    /* Add op code specific parts */
    switch (op_code)
      {
        case LSC_PAUSE:
          proto_tree_add_int(lsc_tree, hf_lsc_stop_npt, tvb, 8, 4,
                             tvb_get_ntohl(tvb, 8));
          break;
        case LSC_RESUME:
          proto_tree_add_int(lsc_tree, hf_lsc_start_npt, tvb, 8, 4,
                             tvb_get_ntohl(tvb, 8));
          proto_tree_add_int(lsc_tree, hf_lsc_scale_num, tvb, 12, 2,
                             tvb_get_ntohs(tvb, 12));
          proto_tree_add_uint(lsc_tree, hf_lsc_scale_denom, tvb, 14, 2,
                              tvb_get_ntohs(tvb, 14));
          break;
        case LSC_JUMP:
        case LSC_PLAY:
          proto_tree_add_int(lsc_tree, hf_lsc_start_npt, tvb, 8, 4,
                             tvb_get_ntohl(tvb, 8));
          proto_tree_add_int(lsc_tree, hf_lsc_stop_npt, tvb, 12, 4,
                             tvb_get_ntohl(tvb, 12));
          proto_tree_add_int(lsc_tree, hf_lsc_scale_num, tvb, 16, 2,
                             tvb_get_ntohs(tvb, 16));
          proto_tree_add_uint(lsc_tree, hf_lsc_scale_denom, tvb, 18, 2,
                              tvb_get_ntohs(tvb, 18));
          break;
        case LSC_DONE:
        case LSC_PAUSE_REPLY:
        case LSC_RESUME_REPLY:
        case LSC_STATUS_REPLY:
        case LSC_RESET_REPLY:
        case LSC_JUMP_REPLY:
        case LSC_PLAY_REPLY:
          proto_tree_add_int(lsc_tree, hf_lsc_current_npt, tvb, 8, 4,
                             tvb_get_ntohl(tvb, 8));
          proto_tree_add_int(lsc_tree, hf_lsc_scale_num, tvb, 12, 2,
                             tvb_get_ntohs(tvb, 12));
          proto_tree_add_uint(lsc_tree, hf_lsc_scale_denom, tvb, 14, 2,
                              tvb_get_ntohs(tvb, 14));
          proto_tree_add_uint(lsc_tree, hf_lsc_mode, tvb, 16, 1,
                              tvb_get_guint8(tvb, 16));
          break;
        default:
          break;
      }
  }
}