Beispiel #1
0
static gboolean
dissect_ses_heur(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
	/* must check that this really is a ses packet */
	int offset = 0;
	guint8 type;
	int len_len;
	guint16 len;

	/* first, check do we have at least 4 bytes (type+length) */
	if (tvb_length(tvb) < 2)
		return FALSE;	/* no */

	/* can we recognize session PDU ? Return FALSE if  not */
	/*   get SPDU type */
	type = tvb_get_guint8(tvb, offset);
	/* check SPDU type */
	if (match_strval(type, ses_vals) == NULL)
	{
		return FALSE;  /* no, it isn't a session PDU */
	}

	/* can we recognize the second session PDU if the first one was
	 * a Give Tokens PDU? Return FALSE if not */
	if(tvb_bytes_exist(tvb, 2, 2) && type == SES_GIVE_TOKENS) {
		/*   get SPDU type */
		type = tvb_get_guint8(tvb, offset+2);
		/* check SPDU type */
		if (match_strval(type, ses_vals) == NULL)
			{
				return FALSE;  /* no, it isn't a session PDU */
			}
	}

	/* some Siemens SIMATIC protocols also use COTP, and shouldn't be 
	 * misinterpreted as SES.
	 * the starter in this case is fixed to 0x32 (SES_MINOR_SYNC_ACK for SES), 
	 * so if the parameter type is unknown, it's probably SIMATIC */
	if(type == 0x32 && tvb_length(tvb) >= 3) {
		type = tvb_get_guint8(tvb, offset+2);
		if (match_strval(type, param_vals) == NULL) {
			return FALSE; /* it's probably a SIMATIC protocol */
		}
	}

	/*  OK,let's check SPDU length  */
	/*  get length of SPDU */
	len = get_item_len(tvb, offset+1, &len_len);

	/*  add header length     */
	len+=len_len;
	/* do we have enough bytes ? */
	if (tvb_length(tvb) < len)
		return FALSE;	/* no */

	dissect_ses(tvb, pinfo, parent_tree);
	return TRUE;
}
Beispiel #2
0
/*
 * Check whether the control field of the packet looks valid.
 */
gboolean
check_xdlc_control(tvbuff_t *tvb, int offset,
  const value_string *u_modifier_short_vals_cmd,
  const value_string *u_modifier_short_vals_resp, gboolean is_response,
  gboolean is_extended _U_)
{
    guint16 control;

    if (!tvb_bytes_exist(tvb, offset, 1))
	return FALSE;	/* not enough data to check */
    switch (tvb_get_guint8(tvb, offset) & 0x03) {

    case XDLC_S:
        /*
	 * Supervisory frame.
	 * No fields to check for validity here.
	 */
	return TRUE;

    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);
	if (is_response) {
		if (match_strval(control & XDLC_U_MODIFIER_MASK,
		    u_modifier_short_vals_resp) == NULL)
			return FALSE;	/* unknown modifier */
	} else {
		if (match_strval(control & XDLC_U_MODIFIER_MASK,
		    u_modifier_short_vals_cmd) == NULL)
			return FALSE;	/* unknown modifier */
	}
	return TRUE;

    default:
	/*
	 * Information frame.
	 * No fields to check for validity here.
	 */
	return TRUE;
    }
}
/*--- dissect_qsig_arg ------------------------------------------------------*/
static int
dissect_qsig_arg(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
  int offset;
  rose_ctx_t *rctx;
  gint32 opcode = 0, service;
  const qsig_op_t *op_ptr;
  const gchar *p;
  proto_item *ti, *ti_tmp;
  proto_tree *qsig_tree;

  offset = 0;
  rctx = get_rose_ctx(pinfo->private_data);
  DISSECTOR_ASSERT(rctx);
  if (rctx->d.pdu != 1)  /* invoke */
    return offset;
  if (rctx->d.code == 0) {  /* local */
    opcode = rctx->d.code_local;
    op_ptr = get_op(opcode);
  } else if (rctx->d.code == 1) {  /* global */
    op_ptr = g_hash_table_lookup(qsig_oid2op_hashtable, rctx->d.code_global);
    if (op_ptr) opcode = op_ptr->opcode;
  } else {
    return offset;
  }
  if (!op_ptr)
    return offset;
  service = get_service(opcode);

  ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, tvb_length(tvb), ENC_NA);
  qsig_tree = proto_item_add_subtree(ti, ett_qsig);

  proto_tree_add_uint(qsig_tree, hf_qsig_operation, tvb, 0, 0, opcode);
  p = match_strval(opcode, VALS(qsig_str_operation));
  if (p) {
    proto_item_append_text(ti, ": %s", p);
    proto_item_append_text(rctx->d.code_item, " - %s", p);
    if (rctx->apdu_depth >= 0)
      proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p);
  }

  ti_tmp = proto_tree_add_uint(qsig_tree, hf_qsig_service, tvb, 0, 0, service);
  p = match_strval(service, VALS(qsig_str_service_name));
  if (p) proto_item_append_text(ti_tmp, " - %s", p);

  if (op_ptr->arg_pdu)
    offset = op_ptr->arg_pdu(tvb, pinfo, qsig_tree);
  else
    if (tvb_length_remaining(tvb, offset) > 0) {
      proto_tree_add_text(qsig_tree, tvb, offset, -1, "UNSUPPORTED ARGUMENT TYPE (QSIG)");
      offset += tvb_length_remaining(tvb, offset);
    }

  return offset;
}
/* check to see if the message is an exclusive message send to host */
static gboolean
csm_to_host(guint16 fc, guint16 ct)
{
    if (fc == 0x0000)
    {
        return (match_strval(ct, exclusive_to_host_ct_vals) != NULL);
    }
    else
    {
        return (match_strval(fc, exclusive_to_host_vals) != NULL);
    }
}
Beispiel #5
0
static void
dissect_operation_tlv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, gint offset, gint length_count)
{
    proto_item *ti;
    proto_tree *oper_tree;
    guint       type, length;

    while (tvb_reported_length_remaining(tvb, offset) >= TLV_TL_LENGTH)
    {
        ti = proto_tree_add_text(tree, tvb, offset, length_count, "Operation TLV");
        oper_tree = proto_item_add_subtree(ti, ett_forces_lfbselect_tlv_type_operation);

        type = tvb_get_ntohs(tvb,offset);
        ti = proto_tree_add_item(oper_tree, hf_forces_lfbselect_tlv_type_operation_type,
                                 tvb, offset, 2, ENC_BIG_ENDIAN);
        if (match_strval(type, operation_type_vals) == NULL)
            expert_add_info_format(pinfo, ti, PI_PROTOCOL, PI_WARN,
                                   "Bogus: ForCES Operation TLV (Type:0x%04x) is not supported", type);

        length = tvb_get_ntohs(tvb, offset+2);
        proto_tree_add_uint_format(oper_tree, hf_forces_lfbselect_tlv_type_operation_length,
                                   tvb, offset+2, 2, length, "Length: %u Bytes", length);

        dissect_path_data_tlv(tvb, pinfo, oper_tree, offset+TLV_TL_LENGTH);
        if (length == 0)
            break;
        offset += length;
    }
}
static gboolean
is_armagetronad_packet(tvbuff_t * tvb)
{
	gint offset = 0;

	/* For each message in the frame */
	while (tvb_length_remaining(tvb, offset) > 2) {
		gint data_len = tvb_get_ntohs(tvb, offset + 4) * 2;

#if 0
		/*
		 * If the descriptor_id is not in the table it's possibly
		 * because the protocol evoluated, losing synchronization
		 * with the table, that's why we don't consider that as
		 * a heuristic
		 */
		if (!match_strval(tvb_get_ntohs(tvb, offset), descriptors))
			/* DescriptorID not found in the table */
			return FALSE;
#endif

		if (!tvb_bytes_exist(tvb, offset + 6, data_len))
			/* Advertised length too long */
			return FALSE;

		offset += 6 + data_len;
	}

	/* The packed should end with a 2 bytes ID */
	return tvb_length_remaining(tvb, offset) == 2;
}
Beispiel #7
0
static const char*
spx_conn_ctrl(guint8 ctrl)
{
	const char *p;

	static const value_string conn_vals[] = {
		{ 0x00,                        "Data, No Ack Required" },
		{ SPX_EOM,                     "End-of-Message" },
		{ SPX_ATTN,                    "Attention" },
		{ SPX_SEND_ACK,                "Acknowledgment Required"},
		{ SPX_SEND_ACK|SPX_EOM,        "Send Ack: End Message"},
		{ SPX_SYS_PACKET,              "System Packet"},
		{ SPX_SYS_PACKET|SPX_SEND_ACK, "System Packet: Send Ack"},
		{ 0x00,                        NULL }
	};

	p = match_strval((ctrl & 0xf0), conn_vals );

	if (p) {
		return p;
	}
	else {
		return "Unknown";
	}
}
Beispiel #8
0
const char *ipprotostr(const int proto) {
    const char *s;

    if ((s = match_strval(proto, ipproto_val)) != NULL)
	return s;

    s = "Unknown";

#ifdef HAVE_GETPROTOBYNUMBER
    /*
     * XXX - have another flag for resolving network-layer
     * protocol names?
     */
    if (g_resolv_flags != 0) {
        static char buf[128];
        struct protoent *pe;
        
	pe = getprotobynumber(proto);
	if (pe) {
	    g_strlcpy(buf, pe->p_name, sizeof(buf));
	    s = buf;
	}
    }
#endif
    return s;
}
Beispiel #9
0
/* dissect_oicq - dissects oicq packet data
 * tvb - tvbuff for packet data (IN)
 * pinfo - packet info
 * proto_tree - resolved protocol tree
 */
static int
dissect_oicq(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree      *oicq_tree;
	proto_item	*ti;
	int offset = 0;

	/* Make sure this packet is for us.                                  */
	/* heuristic: OICQ iff (([0] == STX) && ([3/4] == <valid_command>) ) */
        /*  (Supposedly each OICQ message ends with an ETX so a test for     */
        /*   same could also be part of the heuristic).                      */
	if ( (match_strval(tvb_get_guint8(tvb, 0), oicq_flag_vals)    == NULL) ||
	     (match_strval(tvb_get_ntohs(tvb, 3),  oicq_command_vals) == NULL) )
		return 0;

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

	col_set_str(pinfo->cinfo, COL_INFO, "OICQ Protocol ");


	if (tree) {
		ti = proto_tree_add_item(tree, proto_oicq, tvb, 0, -1, FALSE);
		oicq_tree = proto_item_add_subtree(ti, ett_oicq);

		proto_tree_add_item(oicq_tree, hf_oicq_flag, tvb, offset, 1, FALSE);
		offset += 1;
		
		proto_tree_add_item(oicq_tree, hf_oicq_version, tvb, offset, 2, FALSE);
		offset += 2;

		proto_tree_add_item(oicq_tree, hf_oicq_command, tvb, offset, 2, FALSE);
		offset += 2;


		proto_tree_add_item(oicq_tree, hf_oicq_seq, tvb, offset, 2, FALSE);
		offset += 2;

		proto_tree_add_item(oicq_tree, hf_oicq_qqid, tvb, offset, 4, FALSE);
		offset += 4;
		
		proto_tree_add_item(oicq_tree, hf_oicq_data, tvb, offset, -1, FALSE);
		
		
	}
	
	return tvb_length(tvb);
}
Beispiel #10
0
/* Tries to match val against each element in the value_string array vs.
   Returns the associated string ptr on a match.
   Formats val with fmt, and returns the resulting string, on failure. */
const gchar*
val_to_str(guint32 val, const value_string *vs, const char *fmt) {
  const gchar *ret;

  g_assert(fmt != NULL);

  ret = match_strval(val, vs);
  if (ret != NULL)
    return ret;

  return ep_strdup_printf(fmt, val);
}
Beispiel #11
0
/* Tries to match val against each element in the value_string array vs.
   Returns the associated string ptr on a match.
   Returns 'unknown_str', on failure. */
const gchar*
val_to_str_const(const guint32 val, const value_string *vs, const char *unknown_str) {
  const gchar *ret;

  g_assert(unknown_str != NULL);

  ret = match_strval(val, vs);
  if (ret != NULL)
    return ret;

  return unknown_str;
}
Beispiel #12
0
/* Code to actually dissect the packets */
static int
dissect_llrp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item *ti;
    proto_tree *llrp_tree;
    guint16 type;
    guint32 len;
    guint offset = 0;

    /* Check that there's enough data */
    if (tvb_reported_length(tvb) < LLRP_LEN_MIN)
        return 0;

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

    col_set_str(pinfo->cinfo, COL_INFO, "LLRP Message");

    type = tvb_get_ntohs(tvb, offset) & 0x03FF;

    col_append_fstr(pinfo->cinfo, COL_INFO, " (%s)",
                    val_to_str(type, message_types, "Unknown Type: %d"));

    ti = proto_tree_add_item(tree, proto_llrp, tvb, offset, -1, ENC_NA);
    llrp_tree = proto_item_add_subtree(ti, ett_llrp);

    proto_tree_add_item(llrp_tree, hf_llrp_version, tvb, offset, 1, ENC_NA);
    proto_tree_add_item(llrp_tree, hf_llrp_type, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    ti = proto_tree_add_item(llrp_tree, hf_llrp_length, tvb, offset, 4, ENC_BIG_ENDIAN);
    len = tvb_get_ntohl(tvb, offset);
    if (len > tvb_reported_length(tvb))
    {
        expert_add_info_format(pinfo, ti, PI_MALFORMED, PI_ERROR,
                               "Incorrect length field: claimed %u, but only have %u.",
                               len, tvb_reported_length(tvb));
    }
    offset += 4;

    proto_tree_add_item(llrp_tree, hf_llrp_id, tvb, offset, 4, ENC_BIG_ENDIAN);
    offset += 4;

    if (match_strval(type, message_types))
        dissect_llrp_message(tvb, pinfo, llrp_tree, type, offset);

    return tvb_length(tvb);
}
/*--- dissect_qsig_err ------------------------------------------------------*/
static int
dissect_qsig_err(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
  int offset;
  rose_ctx_t *rctx;
  gint32 errcode;
  const qsig_err_t *err_ptr;
  const gchar *p;
  proto_item *ti;
  proto_tree *qsig_tree;

  offset = 0;
  rctx = get_rose_ctx(pinfo->private_data);
  DISSECTOR_ASSERT(rctx);
  if (rctx->d.pdu != 3)  /* returnError */
    return offset;
  if (rctx->d.code != 0)  /* local */
    return offset;
  errcode = rctx->d.code_local;
  err_ptr = get_err(errcode);
  if (!err_ptr)
    return offset;

  ti = proto_tree_add_item(tree, proto_qsig, tvb, offset, tvb_length(tvb), ENC_NA);
  qsig_tree = proto_item_add_subtree(ti, ett_qsig);

  proto_tree_add_uint(qsig_tree, hf_qsig_error, tvb, 0, 0, errcode);
  p = match_strval(errcode, VALS(qsig_str_error));
  if (p) {
    proto_item_append_text(ti, ": %s", p);
    proto_item_append_text(rctx->d.code_item, " - %s", p);
    if (rctx->apdu_depth >= 0)
      proto_item_append_text(proto_item_get_parent_nth(proto_tree_get_parent(tree), rctx->apdu_depth), " %s", p);
  }

  if (err_ptr->err_pdu)
    offset = err_ptr->err_pdu(tvb, pinfo, qsig_tree);
  else
    if (tvb_length_remaining(tvb, offset) > 0) {
      proto_tree_add_text(qsig_tree, tvb, offset, -1, "UNSUPPORTED ERROR TYPE (QSIG)");
      offset += tvb_length_remaining(tvb, offset);
    }

  return offset;
}
Beispiel #14
0
/* Code to actually dissect the packets - UDP */
static gint
dissect_laplink_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	int offset = 0;
	proto_item *ti;
	proto_tree *laplink_tree;
	guint32 udp_ident;
	const gchar *udp_ident_string;

	/*
	 * Make sure the identifier is reasonable.
	 */
	if (!tvb_bytes_exist(tvb, offset, 4))
		return 0;	/* not enough bytes to check */
	udp_ident = tvb_get_ntohl(tvb, offset);
	udp_ident_string = match_strval(udp_ident, laplink_udp_magic);
	if (udp_ident_string == NULL)
		return 0;	/* unknown */

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

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

	if (tree){
		ti = proto_tree_add_item(tree, proto_laplink, tvb, 0, -1, ENC_NA);
		laplink_tree = proto_item_add_subtree(ti, ett_laplink);

		proto_tree_add_uint(laplink_tree, hf_laplink_udp_ident, tvb, offset, 4, udp_ident);
		offset += 4;

		proto_tree_add_item(laplink_tree, hf_laplink_udp_name, tvb, offset, -1, ENC_ASCII|ENC_NA);
	}
	return tvb_length(tvb);
}
Beispiel #15
0
/* Dissector for xcsl */
static void dissect_xcsl_tcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {

   guint        offset = 0;
   gint         length_remaining;
   guint8       idx;
   gboolean     request;
   guint8       par;
   guint8       str[MAXLEN];
   guint8       result;
   const gchar *code;
   guint        len;
   gint         next_offset;
   proto_item  *xcsl_item = NULL;
   proto_tree  *xcsl_tree = NULL;

   /* color support */
   col_set_str(pinfo->cinfo, COL_PROTOCOL, "Xcsl");
   col_clear(pinfo->cinfo, COL_INFO);

   /* Create display tree for the xcsl protocol */
   if (tree) {
       xcsl_item = proto_tree_add_item(tree, proto_xcsl,tvb, offset, -1, FALSE);
       xcsl_tree = proto_item_add_subtree(xcsl_item, ett_xcsl);
   }

   /* reset idx */
   idx = 0;

   /* reset the parameter count */
   par = 0;

   /* switch whether it concerns a command or an answer */
   request = FALSE;

   while (tvb_reported_length_remaining(tvb, offset) != 0) {

      length_remaining = tvb_ensure_length_remaining(tvb, offset);
      if ( length_remaining == -1 ) {
         return;
      }

      /* get next item */
      if (!(get_next_item(tvb, offset, length_remaining, str, &next_offset, &len))) {
        /* do not continue when get_next_item returns false */
        return;
      }

      /* do not add to the tree when the string is of zero length */
      if ( strlen(str) == 0 ) {
         offset = next_offset + 1;
         continue;
      }

      /* Xcsl (Call Specification Language) protocol in brief :
       *
       * Request :
       *
       *    <xcsl-version>;<transaction-id>;<command>;[parameter1;parameter2;parameter3;....]
       *
       * Reply :
       *
       *    <xcsl-version>;transaction-id;<result>;[answer data;answer data];...
       *
       * If result is one or more digits, this is determined as a Reply.
       *
       * Example :
       *
       * -->      xcsl-1.0;1000;offhook;+31356871234
       * <--      xcsl-1.0;1000;0                              <- success
       *
       * -->      xcsl-1.0;1001;dial;+31356871234;+31356875678
       * <--      xcsl-1.0;1001;0                              <- success
       *
       *
       * index :  0        1    2    3            4
       *
       * Index 2 represents the return code (see the xcsl_action_vals[] definitions)
       *
       */

      /* One by one go through each item ';' separated */
      switch (idx) {

                    /* This is the protocol item */
          case 0:   proto_tree_add_item(tree, hf_xcsl_protocol_version, tvb, offset, len, FALSE);
                    break;

                    /* This should be the transaction ID, if non-digit, it is treated as info */
          case 1:   if ( isdigit(str[0]) ) {
                          proto_tree_add_item(tree, hf_xcsl_transaction_id, tvb, offset, len, FALSE);
                    } else {
                          proto_tree_add_item(tree, hf_xcsl_information, tvb, offset, len, FALSE);
                    }
                    if (check_col(pinfo->cinfo, COL_INFO))
                       col_append_fstr(pinfo->cinfo, COL_INFO, "%s ",str);
                    break;

                    /* Starting with non-digit -> Command, if it starts with a digit -> reply */
          case 2:   if ( isdigit(str[0]) ) {

                      request = FALSE;
                      result = atoi(str);
                      if ( result >= XCSL_NONE ) {
                         result = XCSL_UNDEFINED;
                      }
                      code = match_strval(result, xcsl_action_vals);

                      /* Print result code and description */
                      xcsl_item = proto_tree_add_item(tree, hf_xcsl_result, tvb, offset, len, FALSE);
                      proto_item_append_text(xcsl_item, " (%s)", code);

                      if (result != 0 && check_col(pinfo->cinfo, COL_INFO))
                         col_append_fstr(pinfo->cinfo, COL_INFO, "[%s] ", code);

                    } else {

                      request = TRUE;
                      proto_tree_add_item(tree, hf_xcsl_command, tvb, offset, len, FALSE);

                      if (check_col(pinfo->cinfo, COL_INFO))
                         col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", str);

                    }
                    break;

                    /* This is a command parameter */
          default:  proto_tree_add_item(tree, hf_xcsl_parameter, tvb, offset, len, FALSE);

                    if (check_col(pinfo->cinfo, COL_INFO)) {
                       if ( request == TRUE ) {
                          col_append_fstr(pinfo->cinfo, COL_INFO, ": %s ",str);
                       } else {
                          if (par == 0) {
                             col_append_fstr(pinfo->cinfo, COL_INFO, "reply: %s ",str);
                          } else {
                             col_append_fstr(pinfo->cinfo, COL_INFO, ": %s ",str);
                          }
                       }
                    }

                    /* increment the parameter count */
                    par++;

                    break;
      }

      offset = next_offset + 1;
      idx++;

   }


   return;
}
Beispiel #16
0
static int
dissect_ddtp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree *ddtp_tree = NULL;
    proto_item *ti;

    /*
     * If we don't recognize the version number, don't dissect this.
     */
    if (tvb_length(tvb) >= 4) {
	if (match_strval(tvb_get_ntohl(tvb, 0), vals_ddtp_version) == NULL)
	    return 0;
    }

    /* Indicate what kind of message this is. */
    col_set_str (pinfo->cinfo, COL_PROTOCOL, "DDTP");
    /* In case we throw an exception below. */
    col_clear (pinfo->cinfo, COL_INFO);

    if (tree) {
	ti = proto_tree_add_item(tree, proto_ddtp, tvb, 0, -1, FALSE);
	ddtp_tree = proto_item_add_subtree(ti, ett_ddtp);

	proto_tree_add_item(ddtp_tree, hf_ddtp_version, tvb, 0, 4, FALSE);
	proto_tree_add_item(ddtp_tree, hf_ddtp_encrypt, tvb, 4, 4, FALSE);
	proto_tree_add_item(ddtp_tree, hf_ddtp_hostid, tvb, 8, 4, FALSE);
    }
    if (tvb_get_ntohl(tvb, 4) == DDTP_ENCRYPT_PLAINTEXT) {
	if (tree)
	    proto_tree_add_item(ddtp_tree, hf_ddtp_msgtype, tvb, 12, 4, FALSE);
	switch (tvb_get_ntohl(tvb, 12)) {
	case DDTP_MESSAGE_ERROR :
	    col_set_str(pinfo->cinfo, COL_INFO, "Message Error");
	    break;
	case DDTP_UPDATE_QUERY :
	    col_set_str(pinfo->cinfo, COL_INFO, "Update Query");
	    if (tree) {
		proto_tree_add_item(ddtp_tree, hf_ddtp_opcode, tvb, 16, 4,
			FALSE);
		proto_tree_add_item(ddtp_tree, hf_ddtp_ipaddr, tvb, 20, 4,
			FALSE);
	    }
	    break;
	case DDTP_UPDATE_REPLY :
	    col_set_str(pinfo->cinfo, COL_INFO, "Update Reply");
	    if (tree) {
		proto_tree_add_item(ddtp_tree, hf_ddtp_status, tvb, 16, 4,
			FALSE);
	    }
	    break;
	case DDTP_ALIVE_QUERY :
	    col_set_str(pinfo->cinfo, COL_INFO, "Alive Query");
	    if (tree) {
		proto_tree_add_text(ddtp_tree, tvb, 16, 4, "Dummy : %u",
			tvb_get_ntohl(tvb, 16));
	    }
	    break;
	case DDTP_ALIVE_REPLY :
	    col_set_str(pinfo->cinfo, COL_INFO, "Alive Reply");
	    if (tree) {
		proto_tree_add_text(ddtp_tree, tvb, 16, 4, "Dummy : %u",
			tvb_get_ntohl(tvb, 16));
	    }
	    break;
	default :
	    col_set_str(pinfo->cinfo, COL_INFO, "Unknown type");
	    if (tree) {
		proto_tree_add_text(ddtp_tree, tvb, 12, 4, "Unknown type : %u",
			tvb_get_ntohl(tvb, 12));
	    }
	}
    } else {
	col_set_str(pinfo->cinfo, COL_INFO, "Encrypted payload");
    }
    return tvb_length(tvb);
}
Beispiel #17
0
void
ethertype(guint16 etype, tvbuff_t *tvb, int offset_after_etype,
	  packet_info *pinfo, proto_tree *tree, proto_tree *fh_tree,
	  int etype_id, int trailer_id, int fcs_len)
{
	const char		*description;
	tvbuff_t		*volatile next_tvb;
	guint			length_before;
	gint			captured_length, reported_length;
	volatile gboolean	dissector_found = FALSE;
	const char		*volatile saved_proto;
	void			*pd_save;

	/* Add the Ethernet type to the protocol tree */
	if (tree) {
		proto_tree_add_uint(fh_tree, etype_id, tvb,
				    offset_after_etype - 2, 2, etype);
	}

	/* Get the captured length and reported length of the data
	   after the Ethernet type. */
	captured_length = tvb_length_remaining(tvb, offset_after_etype);
	reported_length = tvb_reported_length_remaining(tvb,
							offset_after_etype);

	/* Remember how much data there is after the Ethernet type,
	   including any trailer and FCS. */
	length_before = reported_length;

	/* Construct a tvbuff for the payload after the Ethernet type.
	   If the FCS length is positive, remove the FCS.
	   (If it's zero, there's no FCS; if it's negative,
	   we don't know whether there's an FCS, so we'll
	   guess based on the length of the trailer.) */
	if (fcs_len > 0) {
		if (captured_length >= 0 && reported_length >= 0) {
			if (reported_length >= fcs_len)
				reported_length -= fcs_len;
			if (captured_length > reported_length)
				captured_length = reported_length;
		}
	}
	next_tvb = tvb_new_subset(tvb, offset_after_etype, captured_length,
				  reported_length);

	pinfo->ethertype = etype;

	/* Look for sub-dissector, and call it if found.
	   Catch exceptions, so that if the reported length of "next_tvb"
	   was reduced by some dissector before an exception was thrown,
	   we can still put in an item for the trailer. */
	saved_proto = pinfo->current_proto;
	pd_save = pinfo->private_data;
	TRY {
		dissector_found = dissector_try_uint(ethertype_dissector_table,
						     etype, next_tvb, pinfo, tree);
	}
	CATCH(BoundsError) {
		/* Somebody threw BoundsError, which means that:

		   1) a dissector was found, so we don't need to
		   dissect the payload as data or update the
		   protocol or info columns;

		   2) dissecting the payload found that the packet was
		   cut off by a snapshot length before the end of
		   the payload.  The trailer comes after the payload,
		   so *all* of the trailer is cut off, and we'll
		   just get another BoundsError if we add the trailer.

		   Therefore, we just rethrow the exception so it gets
		   reported; we don't dissect the trailer or do anything
		   else. */
		RETHROW;
	}
	CATCH(OutOfMemoryError) {
		RETHROW;
	}
	CATCH_ALL {
		/* Somebody threw an exception other than BoundsError, which
		   means that a dissector was found, so we don't need to
		   dissect the payload as data or update the protocol or info
		   columns.  We just show the exception and then drive on
		   to show the trailer, after noting that a dissector was
		   found and restoring the protocol value that was in effect
		   before we called the subdissector. */
		show_exception(next_tvb, pinfo, tree, EXCEPT_CODE, GET_MESSAGE);

		/*  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;
		dissector_found = TRUE;
		pinfo->current_proto = saved_proto;
	}
	ENDTRY;

	if (!dissector_found) {
		/* No sub-dissector found.
		   Label rest of packet as "Data" */
		call_dissector(data_handle,next_tvb, pinfo, tree);

		/* Label protocol */
		col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "0x%04x", etype);

		description = match_strval(etype, etype_vals);
		if (description) {
			col_add_str(pinfo->cinfo, COL_INFO, description);
		}
	}

	add_dix_trailer(pinfo, tree, fh_tree, trailer_id, tvb, next_tvb, offset_after_etype,
			length_before, fcs_len);
}
void
dissect_sss_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, guint8 subfunc, ncp_req_hash_value *request_value)
{
    guint32             foffset=0;
    guint32             subverb=0;
    guint32             msg_length=0;
    guint32             return_code=0;
    guint32             number_of_items=0;
    gint32              length_of_string=0;
    guint32             i = 0;
    const gchar		*str;

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


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

                    }
                    else
                    {
                        proto_tree_add_item(atree, hf_enc_data, tvb, foffset, tvb_length_remaining(tvb, foffset), ENC_NA);
                    }
                }
            }
        }
        else
        {
            proto_tree_add_text(atree, tvb, foffset, 4, "Return Code: Success (0x00000000)");
            if (tvb_length_remaining(tvb, foffset) > 8) {
                foffset += 4;
                proto_tree_add_item(atree, hf_enc_data, tvb, foffset, tvb_length_remaining(tvb, foffset), ENC_NA);
            }
        }
        break;
    case 3:
        break;
    default:
        break;
    }
}
Beispiel #19
0
static void
dissect_ncp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
    gboolean is_tcp)
{
    proto_tree            *ncp_tree = NULL;
    proto_item            *ti;
    struct ncp_ip_header  ncpiph;
    struct ncp_ip_rqhdr   ncpiphrq;
    guint16               ncp_burst_seqno, ncp_ack_seqno;
    guint16               flags = 0;
    proto_tree            *flags_tree = NULL;
    int                   hdr_offset = 0;
    int                   commhdr = 0;
    int                   offset = 0;
    gint                  length_remaining;
    tvbuff_t              *next_tvb;
    guint32               testvar = 0, ncp_burst_command, burst_len, burst_off, burst_file;
    guint8                subfunction;
    guint32               nw_connection = 0, data_offset;
    guint16               data_len = 0;
    guint16               missing_fraglist_count = 0;
    mncp_rhash_value      *request_value = NULL;
    conversation_t        *conversation;
    proto_item            *expert_item;

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

    hdr_offset = 0;
    ncp_hdr = &header;
    commhdr = hdr_offset;

    ti = proto_tree_add_item(tree, proto_ncp, tvb, 0, -1, FALSE);
    ncp_tree = proto_item_add_subtree(ti, ett_ncp);
    if (is_tcp) {
        if (tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RQST && tvb_get_ntohl(tvb, hdr_offset) != NCPIP_RPLY)
            commhdr += 1;
        /* Get NCPIP Header data */
        ncpiph.signature = tvb_get_ntohl(tvb, commhdr);
        proto_tree_add_uint(ncp_tree, hf_ncp_ip_sig, tvb, commhdr, 4, ncpiph.signature);
        ncpiph.length = (0x7fffffff & tvb_get_ntohl(tvb, commhdr+4));
        proto_tree_add_uint(ncp_tree, hf_ncp_ip_length, tvb, commhdr+4, 4, ncpiph.length);
        commhdr += 8;
        if (ncpiph.signature == NCPIP_RQST) {
            ncpiphrq.version = tvb_get_ntohl(tvb, commhdr);
            proto_tree_add_uint(ncp_tree, hf_ncp_ip_ver, tvb, commhdr, 4, ncpiphrq.version);
            commhdr += 4;
            ncpiphrq.rplybufsize = tvb_get_ntohl(tvb, commhdr);
            proto_tree_add_uint(ncp_tree, hf_ncp_ip_rplybufsize, tvb, commhdr, 4, ncpiphrq.rplybufsize);
            commhdr += 4;
        }
        /* Check to see if this is a valid offset, otherwise increment for packet signature */
        if (match_strval(tvb_get_ntohs(tvb, commhdr), ncp_type_vals)==NULL) {
            /* Check to see if we have a valid type after packet signature length */
            if (match_strval(tvb_get_ntohs(tvb, commhdr+8), ncp_type_vals)!=NULL) {
                proto_tree_add_item(ncp_tree, hf_ncp_ip_packetsig, tvb, commhdr, 8, FALSE);
                commhdr += 8;
            }
        }
    } else {
        /* Initialize this structure, we use it below */
        memset(&ncpiph, 0, sizeof(ncpiph));
    }

    header.type         = tvb_get_ntohs(tvb, commhdr);
    header.sequence     = tvb_get_guint8(tvb, commhdr+2);
    header.conn_low     = tvb_get_guint8(tvb, commhdr+3);
    header.task         = tvb_get_guint8(tvb, commhdr+4);
    header.conn_high    = tvb_get_guint8(tvb, commhdr+5);
    proto_tree_add_uint(ncp_tree, hf_ncp_type, tvb, commhdr, 2, header.type);
    nw_connection = (header.conn_high*256)+header.conn_low;

    /* Ok, we need to track the conversation so that we can
     * determine if a new server session is occuring for this
     * connection.
     */
    conversation = find_conversation(pinfo->fd->num, &pinfo->src, &pinfo->dst,
        PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport,
        0);
    if ((ncpiph.length & 0x80000000) || ncpiph.signature == NCPIP_RPLY) {
        /* First time through we will record the initial connection and task
         * values
         */
        if (!pinfo->fd->flags.visited) {
            if (conversation != NULL) {
                /* find the record telling us the
                 * request made that caused this
                 * reply
                 */
                request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
                /* if for some reason we have no
                 * conversation in our hash, create
                 * one */
                if (request_value == NULL) {
                    request_value = mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
                }
            } else {
                /* It's not part of any conversation
                 * - create a new one.
                 */
                conversation = conversation_new(pinfo->fd->num, &pinfo->src,
                    &pinfo->dst, PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0);
                request_value = mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
            }
            /* If this is a request packet then we
             * might have a new task
             */
            if (ncpiph.signature == NCPIP_RPLY) {
                /* Now on reply packets we have to
                 * use the state of the original
                 * request packet, so look up the
                 * request value and check the task number
                 */
                request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
            }
        } else {
            /* Get request value data */
            request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
            if (request_value) {
                if ((request_value->session_start_packet_num == pinfo->fd->num) && ncp_echo_conn)
                {
                    expert_add_info_format(pinfo, NULL, PI_RESPONSE_CODE, PI_CHAT, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task);
                }
            }
        }
    } else {
        if (!pinfo->fd->flags.visited) {
            if (conversation != NULL) {
                /* find the record telling us the
                 * request made that caused this
                 * reply
                 */
                request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
                /* if for some reason we have no
                 * conversation in our hash, create
                 * one */
                if (request_value == NULL) {
                    request_value = mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
                }
            } else {
                /* It's not part of any conversation
                 * - create a new one.
                 */
                conversation = conversation_new(pinfo->fd->num, &pinfo->src,
                    &pinfo->dst, PT_NCP, (guint32) pinfo->srcport, (guint32) pinfo->destport, 0);
                request_value = mncp_hash_insert(conversation, nw_connection, header.task, pinfo);
            }
            /* find the record telling us the request
             * made that caused this reply
             */
        } else {
            request_value = mncp_hash_lookup(conversation, nw_connection, header.task);
            if (request_value) {
                if ((request_value->session_start_packet_num == pinfo->fd->num) && ncp_echo_conn)
                {
                    expert_add_info_format(pinfo, NULL, PI_RESPONSE_CODE, PI_CHAT, "Detected New Server Session. Connection %d, Task %d", nw_connection, header.task);
                }
            }
        }
    }

    tap_queue_packet(ncp_tap.hdr, pinfo, ncp_hdr);

    if (check_col(pinfo->cinfo, COL_INFO)) {
        col_add_str(pinfo->cinfo, COL_INFO,
            val_to_str(header.type, ncp_type_vals, "Unknown type (0x%04x)"));
    }

    /*
     * Process the packet-type-specific header.
     */
    switch (header.type) {

    case NCP_BROADCAST_SLOT:    /* Server Broadcast */
        proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence);
        proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
        proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, FALSE);
        proto_tree_add_item(ncp_tree, hf_ncp_oplock_flag, tvb, commhdr + 9, 1, tvb_get_guint8(tvb, commhdr+9));
        proto_tree_add_item(ncp_tree, hf_ncp_oplock_handle, tvb, commhdr + 10, 4, FALSE);
        if ((tvb_get_guint8(tvb, commhdr+9)==0x24) && ncp_echo_file)
        {
            expert_add_info_format(pinfo, NULL, PI_RESPONSE_CODE, PI_CHAT, "Server requesting station to clear oplock on handle - %08x", tvb_get_ntohl(tvb, commhdr+10));
        }
        break;

    case NCP_LIP_ECHO:    /* Lip Echo Packet */
        proto_tree_add_item(ncp_tree, hf_lip_echo, tvb, commhdr, 13, FALSE);
        break;

    case NCP_BURST_MODE_XFER:    /* Packet Burst Packet */
        /*
         * XXX - we should keep track of whether there's a burst
         * outstanding on a connection and, if not, treat the
         * beginning of the data as a burst header.
         *
         * The burst header contains:
         *
         *    4 bytes of little-endian function number:
         *        1 = read, 2 = write;
         *
         *    4 bytes of file handle;
         *
         *    8 reserved bytes;
         *
         *    4 bytes of big-endian file offset;
         *
         *    4 bytes of big-endian byte count.
         *
         * The data follows for a burst write operation.
         *
         * The first packet of a burst read reply contains:
         *
         *    4 bytes of little-endian result code:
         *       0: No error
         *       1: Initial error
         *       2: I/O error
         *       3: No data read;
         *
         *    4 bytes of returned byte count (big-endian?).
         *
         * The data follows.
         *
         * Each burst of a write request is responded to with a
         * burst packet with a 2-byte little-endian result code:
         *
         *    0: Write successful
         *    4: Write error
         */
        flags = tvb_get_guint8(tvb, commhdr + 2);

        ti = proto_tree_add_uint(ncp_tree, hf_ncp_system_flags,
            tvb, commhdr + 2, 1, flags);
        flags_tree = proto_item_add_subtree(ti, ett_ncp_system_flags);

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_abt,
            tvb, commhdr + 2, 1, FALSE);
        if (flags & ABT) {
            proto_item_append_text(ti, "  ABT");
        }
        flags&=(~( ABT ));

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_bsy,
            tvb, commhdr + 2, 1, FALSE);
        if (flags & BSY) {
            proto_item_append_text(ti, "  BSY");
        }
        flags&=(~( BSY ));

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_eob,
            tvb, commhdr + 2, 1, FALSE);
        if (flags & EOB) {
            proto_item_append_text(ti, "  EOB");
        }
        flags&=(~( EOB ));

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_lst,
            tvb, commhdr + 2, 1, FALSE);
        if (flags & LST) {
            proto_item_append_text(ti, "  LST");
        }
        flags&=(~( LST ));

        proto_tree_add_item(flags_tree, hf_ncp_system_flags_sys,
            tvb, commhdr + 2, 1, FALSE);
        if (flags & SYS) {
            proto_item_append_text(ti, "  SYS");
        }
        flags&=(~( SYS ));


        proto_tree_add_item(ncp_tree, hf_ncp_stream_type,
            tvb, commhdr + 3, 1, FALSE);
        proto_tree_add_item(ncp_tree, hf_ncp_src_connection,
            tvb, commhdr + 4, 4, FALSE);
        proto_tree_add_item(ncp_tree, hf_ncp_dst_connection,
            tvb, commhdr + 8, 4, FALSE);
        proto_tree_add_item(ncp_tree, hf_ncp_packet_seqno,
            tvb, commhdr + 12, 4, FALSE);
        proto_tree_add_item(ncp_tree, hf_ncp_delay_time,
            tvb, commhdr + 16, 4, FALSE);
        ncp_burst_seqno = tvb_get_ntohs(tvb, commhdr+20);
        proto_tree_add_item(ncp_tree, hf_ncp_burst_seqno,
            tvb, commhdr + 20, 2, FALSE);
        ncp_ack_seqno = tvb_get_ntohs(tvb, commhdr+22);
        proto_tree_add_item(ncp_tree, hf_ncp_ack_seqno,
            tvb, commhdr + 22, 2, FALSE);
        proto_tree_add_item(ncp_tree, hf_ncp_burst_len,
            tvb, commhdr + 24, 4, FALSE);
        data_offset = tvb_get_ntohl(tvb, commhdr + 28);
        proto_tree_add_uint(ncp_tree, hf_ncp_data_offset,
            tvb, commhdr + 28, 4, data_offset);
        data_len = tvb_get_ntohs(tvb, commhdr + 32);
        proto_tree_add_uint(ncp_tree, hf_ncp_data_bytes,
            tvb, commhdr + 32, 2, data_len);
        missing_fraglist_count = tvb_get_ntohs(tvb, commhdr + 34);
        proto_tree_add_item(ncp_tree, hf_ncp_missing_fraglist_count,
            tvb, commhdr + 34, 2, FALSE);
        offset = commhdr + 36;
        if (!(flags & SYS) && ncp_burst_seqno == ncp_ack_seqno &&
            data_offset == 0) {
            /*
             * This is either a Burst Read or Burst Write
             * command.  The data length includes the burst
             * mode header, plus any data in the command
             * (there shouldn't be any in a read, but there
             * might be some in a write).
             */
            if (data_len < 4)
                return;
            ncp_burst_command = tvb_get_ntohl(tvb, offset);
            proto_tree_add_item(ncp_tree, hf_ncp_burst_command,
                tvb, offset, 4, FALSE);
            offset += 4;
            data_len -= 4;

            if (data_len < 4)
                return;
            burst_file = tvb_get_ntohl(tvb, offset);
            proto_tree_add_item(ncp_tree, hf_ncp_burst_file_handle,
                tvb, offset, 4, FALSE);
            offset += 4;
            data_len -= 4;

            if (data_len < 8)
                return;
            proto_tree_add_item(ncp_tree, hf_ncp_burst_reserved,
                tvb, offset, 8, FALSE);
            offset += 8;
            data_len -= 8;

            if (data_len < 4)
                return;
            burst_off = tvb_get_ntohl(tvb, offset);
            proto_tree_add_uint(ncp_tree, hf_ncp_burst_offset,
                tvb, offset, 4, burst_off);
            offset += 4;
            data_len -= 4;

            if (data_len < 4)
                return;
            burst_len = tvb_get_ntohl(tvb, offset);
            proto_tree_add_uint(ncp_tree, hf_ncp_burst_len,
                tvb, offset, 4, burst_len);
            offset += 4;
            data_len -= 4;

            if (check_col(pinfo->cinfo, COL_INFO)) {
                col_add_fstr(pinfo->cinfo, COL_INFO,
                    "%s %d bytes starting at offset %d in file 0x%08x",
                    val_to_str(ncp_burst_command,
                      burst_command, "Unknown (0x%08x)"),
                     burst_len, burst_off, burst_file);
            }
            break;
        } else {
            if (tvb_get_guint8(tvb, commhdr + 2) & 0x10) {
                col_set_str(pinfo->cinfo, COL_INFO, "End of Burst");
            }
        }
        break;

    case NCP_ALLOCATE_SLOT:        /* Allocate Slot Request */
        length_remaining = tvb_length_remaining(tvb, commhdr + 4);
        if (length_remaining > 4) {
            testvar = tvb_get_ntohl(tvb, commhdr+4);
            if (testvar == 0x4c495020) {
                proto_tree_add_item(ncp_tree, hf_lip_echo, tvb, commhdr+4, 13, FALSE);
                break;
            }
        }
        /* otherwise fall through */

    case NCP_POSITIVE_ACK:        /* Positive Acknowledgement */
    case NCP_SERVICE_REQUEST:    /* Server NCP Request */
    case NCP_SERVICE_REPLY:        /* Server NCP Reply */
    case NCP_WATCHDOG:        /* Watchdog Packet */
    case NCP_DEALLOCATE_SLOT:    /* Deallocate Slot Request */
    default:
        proto_tree_add_uint(ncp_tree, hf_ncp_seq, tvb, commhdr + 2, 1, header.sequence);
        proto_tree_add_uint(ncp_tree, hf_ncp_connection,tvb, commhdr + 3, 3, nw_connection);
        proto_tree_add_item(ncp_tree, hf_ncp_task, tvb, commhdr + 4, 1, FALSE);
        break;
    }

    /*
     * Process the packet body.
     */
    switch (header.type) {

    case NCP_ALLOCATE_SLOT:        /* Allocate Slot Request */
        length_remaining = tvb_length_remaining(tvb, commhdr + 4);
        if (length_remaining > 4) {
            testvar = tvb_get_ntohl(tvb, commhdr+4);
            if (testvar == 0x4c495020) {
                proto_tree_add_text(ncp_tree, tvb, commhdr, -1,
                    "Lip Echo Packet");
                /*break;*/
            }
        }
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        dissect_ncp_request(next_tvb, pinfo, nw_connection,
            header.sequence, header.type, ncp_tree);
        break;

    case NCP_DEALLOCATE_SLOT:    /* Deallocate Slot Request */
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        dissect_ncp_request(next_tvb, pinfo, nw_connection,
            header.sequence, header.type, ncp_tree);
        break;

    case NCP_SERVICE_REQUEST:    /* Server NCP Request */
    case NCP_BROADCAST_SLOT:    /* Server Broadcast Packet */
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        if (tvb_get_guint8(tvb, commhdr+6) == 0x68) {
            subfunction = tvb_get_guint8(tvb, commhdr+7);
            switch (subfunction) {

            case 0x02:    /* NDS Frag Packet to decode */
                dissect_nds_request(next_tvb, pinfo,
                    nw_connection, header.sequence,
                    header.type, ncp_tree);
                break;

            case 0x01:    /* NDS Ping */
                dissect_ping_req(next_tvb, pinfo,
                    nw_connection, header.sequence,
                    header.type, ncp_tree);
                break;

            default:
                dissect_ncp_request(next_tvb, pinfo,
                    nw_connection, header.sequence,
                    header.type, ncp_tree);
                break;
             }
        } else {
            dissect_ncp_request(next_tvb, pinfo, nw_connection,
                header.sequence, header.type, ncp_tree);
        }
        break;

    case NCP_SERVICE_REPLY:        /* Server NCP Reply */
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        nds_defrag(next_tvb, pinfo, nw_connection, header.sequence,
            header.type, ncp_tree, &ncp_tap);
        break;

    case NCP_POSITIVE_ACK:        /* Positive Acknowledgement */
        /*
         * XXX - this used to call "nds_defrag()", which would
         * clear out "frags".  Was that the right thing to
         * do?
         */
        next_tvb = tvb_new_subset_remaining(tvb, commhdr);
        dissect_ncp_reply(next_tvb, pinfo, nw_connection,
            header.sequence, header.type, ncp_tree, &ncp_tap);
        break;

    case NCP_WATCHDOG:        /* Watchdog Packet */
        /*
         * XXX - should the completion code be interpreted as
         * it is in "packet-ncp2222.inc"?  If so, this
         * packet should be handled by "dissect_ncp_reply()".
         */
        proto_tree_add_item(ncp_tree, hf_ncp_completion_code,
            tvb, commhdr + 6, 1, TRUE);
        proto_tree_add_item(ncp_tree, hf_ncp_connection_status,
            tvb, commhdr + 7, 1, TRUE);
        proto_tree_add_item(ncp_tree, hf_ncp_slot,
            tvb, commhdr + 8, 1, TRUE);
        proto_tree_add_item(ncp_tree, hf_ncp_control_code,
            tvb, commhdr + 9, 1, TRUE);
        /*
         * Display the rest of the packet as data.
         */
        if (tvb_offset_exists(tvb, commhdr + 10)) {
            call_dissector(data_handle,
                tvb_new_subset_remaining(tvb, commhdr + 10),
                pinfo, ncp_tree);
        }
        break;

    case NCP_BURST_MODE_XFER:    /* Packet Burst Packet */
        if (flags & SYS) {
            /*
             * System packet; show missing fragments if there
             * are any.
             */
            while (missing_fraglist_count != 0) {
                proto_tree_add_item(ncp_tree, hf_ncp_missing_data_offset,
                    tvb, offset, 4, FALSE);
                offset += 4;
                proto_tree_add_item(ncp_tree, hf_ncp_missing_data_count,
                    tvb, offset, 2, FALSE);
                offset += 2;
                missing_fraglist_count--;
            }
        } else {
            /*
             * XXX - do this by using -1 and -1 as the length
             * arguments to "tvb_new_subset()" and then calling
             * "tvb_set_reported_length()"?  That'll throw an
             * exception if "data_len" goes past the reported
             * length of the packet, but that's arguably a
             * feature in this case.
             */
            length_remaining = tvb_length_remaining(tvb, offset);
            if (length_remaining > data_len)
                length_remaining = data_len;
            if (data_len != 0) {
                call_dissector(data_handle,
                    tvb_new_subset(tvb, offset,
                    length_remaining, data_len),
                    pinfo, ncp_tree);
            }
        }
        break;

    case NCP_LIP_ECHO:        /* LIP Echo Packet */
        proto_tree_add_text(ncp_tree, tvb, commhdr, -1,
            "Lip Echo Packet");
        break;

    default:
        expert_item = proto_tree_add_text(ncp_tree, tvb, commhdr + 6, -1,
            "%s packets not supported yet",
            val_to_str(header.type, ncp_type_vals,
                "Unknown type (0x%04x)"));
        if (ncp_echo_err) {
            expert_add_info_format(pinfo, expert_item, PI_UNDECODED, PI_NOTE, "%s packets not supported yet", val_to_str(header.type, ncp_type_vals,
                "Unknown type (0x%04x)"));
        }
        break;
    }
}
Beispiel #20
0
static
void dissect_pw_cesopsn( tvbuff_t * tvb_original
						,packet_info * pinfo
						,proto_tree * tree
						,pwc_demux_type_t demux)
{
	const int encaps_size = 4; /*RTP header in encapsulation is not supported yet*/
	gint packet_size;
	gint payload_size;
	gint padding_size;
	pwc_packet_properties_t properties;

	packet_size = tvb_reported_length_remaining(tvb_original, 0);

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

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

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

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

			if (payload_size_from_cw < 0)
			{
				properties |= PWC_CW_BAD_PAYLEN_LT_0;
			}
			else if (payload_size_from_cw > payload_size_from_packet)
			{
				properties |= PWC_CW_BAD_PAYLEN_GT_PACKET;
			}
			else if (payload_size_from_packet >= 64)
			{
				properties |= PWC_CW_BAD_LEN_MUST_BE_0;
			}
			else /* ok */
			{
				payload_size = payload_size_from_cw;
				padding_size = payload_size_from_packet - payload_size_from_cw; /* >=0 */
			}
		}
		else
		{
			payload_size = payload_size_from_packet;
			padding_size = 0;
		}
	}

	{
		guint8 cw_lm;
		cw_lm = tvb_get_guint8(tvb_original, 0) & 0x0b /*l+mod*/;
		if (NULL == match_strval(cw_lm, vals_cw_lm))
		{
			properties |= PWC_CW_SUSPECT_LM;
		}

		{
			guint8 l_bit, m_bits;
			l_bit  = (cw_lm & 0x08) >> 3;
			m_bits = (cw_lm & 0x03) >> 0;
			if ((l_bit == 0 && m_bits == 0x0) /*CESoPSN data packet - normal situation*/
			    ||(l_bit == 0 && m_bits == 0x2) /*CESoPSN data packet - RDI on the AC*/ )
			{
				if ((payload_size == 0) || ((payload_size % 8) != 0))
				{
					properties |= PWC_PAY_SIZE_BAD;
				}
			}
			else if (l_bit == 1 && m_bits == 0x0) /*TDM data is invalid; payload MAY be omitted*/
			{
				/*allow any size of payload*/
			}
			else /*reserved combinations*/
			{
				/*allow any size of payload*/
			}
		}
	}

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

		if (properties & PWC_PAY_SIZE_BAD)
		{
			col_append_str(pinfo->cinfo, COL_INFO, "Payload size:Bad, ");
		}

		col_append_fstr(pinfo->cinfo, COL_INFO, "TDM octets:%d", (int)payload_size);

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

	{
		proto_item* item;
		item = proto_tree_add_item(tree, proto, tvb_original, 0, -1, ENC_NA);
		pwc_item_append_cw(item,tvb_get_ntohl(tvb_original, 0),TRUE);
		pwc_item_append_text_n_items(item,(int)payload_size,"octet");
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				proto_item* item2;
				tvb = tvb_new_subset(tvb_original, 0, PWC_SIZEOF_CW, PWC_SIZEOF_CW);
				item2 = proto_tree_add_item(tree2, hf_cw, tvb, 0, -1, ENC_NA);
				pwc_item_append_cw(item2,tvb_get_ntohl(tvb, 0),FALSE);
				{
					proto_tree* tree3;
					tree3 = proto_item_add_subtree(item, ett);
					{
						proto_item* item3;
						if (properties & PWC_CW_BAD_BITS03) /*display only if value is wrong*/
						{
							item3 = proto_tree_add_item(tree3, hf_cw_bits03, tvb, 0, 1, ENC_BIG_ENDIAN);
							expert_add_info_format(pinfo, item3, PI_MALFORMED, PI_ERROR
								,"Bits 0..3 of Control Word must be 0");
						}

						item3 = proto_tree_add_item(tree3, hf_cw_lm,  tvb, 0, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_SUSPECT_LM)
						{
							expert_add_info_format(pinfo, item3, PI_UNDECODED, PI_WARN
								,"Reserved combination of L and Modifier bits");
						}

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

						item3 = proto_tree_add_item(tree3, hf_cw_frg, tvb, 1, 1, ENC_BIG_ENDIAN);
						if (properties & PWC_CW_BAD_FRAG)
						{
							expert_add_info_format(pinfo, item3, PI_MALFORMED, PI_ERROR
								,"Fragmentation of payload is not allowed"
								" for basic CESoPSN mode");
						}

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

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

					}
				}
			}
		}

		/* payload */
		if (payload_size == 0)
		{
			if (properties & PWC_PAY_SIZE_BAD)
			{
				expert_add_info_format(pinfo, item, PI_MALFORMED, PI_ERROR
					,"CESoPSN payload: none found. Size of payload must be <> 0");
			}
			else
			{
				expert_add_info_format(pinfo, item, PI_UNDECODED, PI_NOTE
					,"CESoPSN payload: omitted to conserve bandwidth");
			}
		}
		else
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				proto_item* item2;
				tvbuff_t* tvb;
				tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW, payload_size, payload_size);
				item2 = proto_tree_add_item(tree2, hf_payload, tvb, 0, -1, ENC_NA);
				pwc_item_append_text_n_items(item2,(int)payload_size,"octet");
				if (properties & PWC_PAY_SIZE_BAD)
				{
					expert_add_info_format(pinfo, item2, PI_MALFORMED, PI_ERROR
						,"CESoPSN packet payload size must be multiple of 8");
				}
				tree2 = proto_item_add_subtree(item2, ett);
				call_dissector(data_handle, tvb, pinfo, tree2);
				item2 = proto_tree_add_int(tree2, hf_payload_l, tvb, 0, 0
					,(int)payload_size); /* allow filtering */
				PROTO_ITEM_SET_HIDDEN(item2);
			}
		}

		/* padding */
		if (padding_size > 0)
		{
			proto_tree* tree2;
			tree2 = proto_item_add_subtree(item, ett);
			{
				tvbuff_t* tvb;
				tvb = tvb_new_subset(tvb_original, PWC_SIZEOF_CW + payload_size, padding_size, -1);
				call_dissector(pw_padding_handle, tvb, pinfo, tree2);
			}
		}
	}
	return;
}
guint16 dissect_cbs_message_identifier(tvbuff_t *tvb, proto_tree *tree, guint16 offset)
{
   guint16 msg_id;
   const char *msg_id_string = NULL;

   msg_id = tvb_get_ntohs(tvb, offset);
   msg_id_string = match_strval(msg_id, message_id_values);
   if (msg_id_string == NULL)
   {
      if (msg_id < 1000)
      {
         msg_id_string = "Message ID to be allocated by GSMA";
      }
      else if (msg_id < 4096)
      {
         msg_id_string = "Message ID intended for standardization in future versions of 3GPP TS 23.041";
      }
      else if (msg_id < 4224)
      {
         msg_id_string = "Message ID reserved for Cell Broadcast Data Download (unsecured) to the SIM ";
      }
      else if (msg_id < 4352)
      {
         msg_id_string = "Message ID reserved for Cell Broadcast Data Download (secured) to the SIM ";
      }
      else if (msg_id < 4360)
      {
         msg_id_string = "ETWS CBS Message Identifier for future extension";
      }
      else if (msg_id < 4400)
      {
         msg_id_string = "CMAS CBS Message Identifier for future extension";
      }
      else if (msg_id < 6400)
      {
         msg_id_string = "CBS Message Identifier for future PWS use";
      }
      else if (msg_id < 40960)
      {
         msg_id_string = "Intended for standardization in future versions of 3GPP TS 23.041";
      }
      else if (msg_id < 43500)
      {
         msg_id_string = "Message ID in PLMN operator specific range";
      }
      else if (msg_id < 43530)
      {
         msg_id_string = "Traffic Information Traffic Master UK";
      }
      else if (msg_id < 43585)
      {
         msg_id_string = "Traffic information Mannesmann Telecommerce";
      }
      else if (msg_id < 45056)
      {
         msg_id_string = "Message ID in PLMN operator specific range";
      }
      else
      {
         msg_id_string = "Message ID intended as PLMN operator specific range in future versions of 3GPP TS 23.041";
      }
   }
   proto_tree_add_uint_format_value(tree, hf_gsm_cbs_message_identifier, tvb, offset, 2, msg_id, "%s (%d)", msg_id_string, msg_id);
   return 2;
}
Beispiel #22
0
static int
dissect_bvlc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{

	proto_item *ti;
	proto_item *ti_bdt;
	proto_item *ti_fdt;
	proto_tree *bvlc_tree;
	proto_tree *bdt_tree; /* Broadcast Distribution Table */
	proto_tree *fdt_tree; /* Foreign Device Table */

	gint offset;
	guint8 bvlc_type;
	guint8 bvlc_function;
	guint16 bvlc_length;
	guint16 packet_length;
	guint npdu_length;
	guint length_remaining;
	guint16 bvlc_result;
	tvbuff_t *next_tvb;

	offset = 0;

	bvlc_type =  tvb_get_guint8(tvb, offset);

	/*
	 * Simple sanity check - make sure the type is one we know about.
	 */
	if (match_strval(bvlc_type, bvlc_types) == NULL)
		return 0;

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

	col_set_str(pinfo->cinfo, COL_INFO, "BACnet Virtual Link Control");

	bvlc_function = tvb_get_guint8(tvb, offset+1);
	packet_length = tvb_get_ntohs(tvb, offset+2);
	length_remaining = tvb_reported_length_remaining(tvb, offset);
	if (bvlc_function > 0x08) {
		/*  We have a constant header length of BVLC of 4 in every
		 *  BVLC-packet forewarding an NPDU. Beware: Changes in the
		 *  BACnet-IP-standard may break this.
		 *  At the moment, no functions above 0x0b
		 *  exist (Addendum 135a to ANSI/ASHRAE 135-1995 - BACnet)
		 */
		bvlc_length = 4;
	} else if(bvlc_function == 0x04) {
		/* 4 Bytes + 6 Bytes for B/IP Address of Originating Device */
		bvlc_length = 10;
	} else {
		/*  BVLC-packets with function below 0x09 contain
		 *  routing-level data (e.g. Broadcast Distribution)
		 *  but no NPDU for BACnet, so bvlc_length goes up to the end
		 *  of the captured frame.
		 */
		bvlc_length = packet_length;
	}

	if (tree) {
		if (bvlc_length < 4) {
			proto_tree_add_text(tree, tvb, 2, 2,
				"Bogus length: %d", bvlc_length);
			return tvb_reported_length(tvb);	/* XXX - reject? */
		}
		ti = proto_tree_add_item(tree, proto_bvlc, tvb, 0,
			bvlc_length, ENC_NA);
		bvlc_tree = proto_item_add_subtree(ti, ett_bvlc);
		proto_tree_add_uint(bvlc_tree, hf_bvlc_type, tvb, offset, 1,
			bvlc_type);
		offset ++;
		proto_tree_add_uint(bvlc_tree, hf_bvlc_function, tvb,
			offset, 1, bvlc_function);
		offset ++;
		if (length_remaining != packet_length)
			proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_length, tvb, offset,
				2, bvlc_length,
				"%d of %d bytes (invalid length - expected %d bytes)",
				bvlc_length, packet_length, length_remaining);
		else
			proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_length, tvb, offset,
				2, bvlc_length, "%d of %d bytes BACnet packet length",
				bvlc_length, packet_length);
		offset += 2;
		switch (bvlc_function) {
		case 0x00: /* BVLC-Result */
			bvlc_result = tvb_get_ntohs(tvb, offset);
			/* I dont know why the result code is encoded in 4 nibbles,
			 * but only using one: 0x00r0. Shifting left 4 bits.
			 */
			/* We should bitmask the result correctly when we have a
		 	* packet to dissect, see README.developer, 1.6.2, FID */
			proto_tree_add_uint_format_value(bvlc_tree, hf_bvlc_result, tvb,
				offset, 2, bvlc_result,"0x%04x (%s)",
				bvlc_result, val_to_str(bvlc_result,
					bvlc_result_names, "Unknown"));
			offset += 2;
			break;
		case 0x01: /* Write-Broadcast-Distribution-Table */
		case 0x03: /* Read-Broadcast-Distribution-Table-Ack */
			/* List of BDT Entries:	N*10-octet */
			ti_bdt = proto_tree_add_item(bvlc_tree, proto_bvlc, tvb,
				offset, bvlc_length-4, ENC_NA);
			bdt_tree = proto_item_add_subtree(ti_bdt, ett_bdt);
			/* List of BDT Entries:	N*10-octet */
			while ((bvlc_length - offset) > 9) {
				proto_tree_add_item(bdt_tree, hf_bvlc_bdt_ip,
					tvb, offset, 4, ENC_BIG_ENDIAN);
				offset += 4;
				proto_tree_add_item(bdt_tree, hf_bvlc_bdt_port,
					tvb, offset, 2, ENC_BIG_ENDIAN);
				offset += 2;
				proto_tree_add_item(bdt_tree,
					hf_bvlc_bdt_mask, tvb, offset, 4,
					ENC_NA);
				offset += 4;
			}
			/* We check this if we get a BDT-packet somewhere */
			break;
		case 0x02: /* Read-Broadcast-Distribution-Table */
			/* nothing to do here */
			break;
		case 0x05: /* Register-Foreign-Device */
			/* Time-to-Live	2-octets T, Time-to-Live T, in seconds */
			proto_tree_add_item(bvlc_tree, hf_bvlc_reg_ttl,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			break;
		case 0x06: /* Read-Foreign-Device-Table */
			/* nothing to do here */
			break;
		case 0x07: /* Read-Foreign-Device-Table-Ack */
			/* List of FDT Entries:	N*10-octet */
			/* N indicates the number of entries in the FDT whose
			 * contents are being returned. Each returned entry
			 * consists of the 6-octet B/IP address of the registrant;
			 * the 2-octet Time-to-Live value supplied at the time of
			 * registration; and a 2-octet value representing the
			 * number of seconds remaining before the BBMD will purge
			 * the registrant's FDT entry if no re-registration occurs.
			 */
			ti_fdt = proto_tree_add_item(bvlc_tree, proto_bvlc, tvb,
				offset, bvlc_length -4, ENC_NA);
			fdt_tree = proto_item_add_subtree(ti_fdt, ett_fdt);
			/* List of FDT Entries:	N*10-octet */
			while ((bvlc_length - offset) > 9) {
				proto_tree_add_item(fdt_tree, hf_bvlc_fdt_ip,
					tvb, offset, 4, ENC_BIG_ENDIAN);
				offset += 4;
				proto_tree_add_item(fdt_tree, hf_bvlc_fdt_port,
					tvb, offset, 2, ENC_BIG_ENDIAN);
				offset += 2;
				proto_tree_add_item(fdt_tree,
					hf_bvlc_fdt_ttl, tvb, offset, 2,
					ENC_BIG_ENDIAN);
				offset += 2;
				proto_tree_add_item(fdt_tree,
					hf_bvlc_fdt_timeout, tvb, offset, 2,
					ENC_BIG_ENDIAN);
				offset += 2;
			}
			/* We check this if we get a FDT-packet somewhere */
			break;
		case 0x08: /* Delete-Foreign-Device-Table-Entry */
			/* FDT Entry:	6-octets */
			proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_ip,
				tvb, offset, 4, ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(bvlc_tree, hf_bvlc_fdt_port,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
			break;
			/* We check this if we get a FDT-packet somewhere */
		case 0x04:	/* Forwarded-NPDU
				 * Why is this 0x04? It would have been a better
				 * idea to append all forewarded NPDUs at the
				 * end of the function table in the B/IP-standard!
				 */
			/* proto_tree_add_bytes_format(); */
			proto_tree_add_item(bvlc_tree, hf_bvlc_fwd_ip,
				tvb, offset, 4, ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(bvlc_tree, hf_bvlc_fwd_port,
				tvb, offset, 2, ENC_BIG_ENDIAN);
			offset += 2;
		default:/* Distribute-Broadcast-To-Network
			 * Original-Unicast-NPDU
			 * Original-Broadcast-NPDU
			 * Going to the next dissector...
			 */
			break;
		}

	}
/* Ok, no routing information BVLC packet. Dissect as
 * BACnet NPDU
 */
	npdu_length = packet_length - bvlc_length;
	next_tvb = tvb_new_subset(tvb,bvlc_length,-1,npdu_length);
	/* Code from Guy Harris */
	if (!dissector_try_uint(bvlc_dissector_table,
	    bvlc_function, next_tvb, pinfo, tree)) {
		/* Unknown function - dissect the paylod as data */
		call_dissector(data_handle,next_tvb, pinfo, tree);
	}
	return tvb_reported_length(tvb);
}
Beispiel #23
0
/* Code to actually dissect the packets */
static int
dissect_mbtcp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Set up structures needed to add the protocol subtree and manage it */
	mbtcp_hdr	mh;
	proto_item	*mi, *mf;
	proto_tree	*mbtcp_tree, *modbus_tree, *group_tree;
	int		offset, group_offset, packet_type;
	guint		i;
	gint		packet_len, payload_start, payload_len;
	const char	*func_string = "";
	const char	*pkt_type_str = "";
	const char	*err_str = "";
	guint32		byte_cnt, group_byte_cnt, group_word_cnt;
	guint32		packet_num;	/* num to uniquely identify different mbtcp
					 * packets in one packet */
	guint8		exception_code;
	gboolean	exception_returned;
	guint8		fc;

	mh.transaction_id = tvb_get_ntohs(tvb, 0);
	mh.protocol_id = tvb_get_ntohs(tvb, 2);
	mh.len = tvb_get_ntohs(tvb, 4);
	mh.mdbs_hdr.unit_id = tvb_get_guint8(tvb, 6);
	mh.mdbs_hdr.function_code = tvb_get_guint8(tvb, 7);


	/* check that it actually looks like Modbus/TCP */
	/* protocol id == 0 */
	if( mh.protocol_id != 0 ){
		return 0;
	}
	/* length is at least 2 (unit_id + function_code) */
	if( mh.len < 2 ){
		return 0;
	}
	/* function code is in the set 1-24, 40, 125-127.
	 * Note that function code is only 7 bits.
	 */
	fc=mh.mdbs_hdr.function_code&0x7f;
	if(!match_strval(fc, function_code_vals))
		return 0;


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

	col_clear(pinfo->cinfo, COL_INFO);


	/* Make entries in Info column on summary display */
	offset = 0;

	if ( mh.mdbs_hdr.function_code & 0x80 ) {
		exception_code = tvb_get_guint8(tvb, offset + sizeof(mbtcp_hdr));
		mh.mdbs_hdr.function_code ^= 0x80;
		exception_returned = TRUE;
	}
	else {
		exception_code = 0;
		exception_returned = FALSE;
	}
	func_string = val_to_str(mh.mdbs_hdr.function_code, function_code_vals,
	    "Unknown function (%u)");
	if (check_col(pinfo->cinfo, COL_INFO))
	{
		packet_type = classify_packet(pinfo);
		switch ( packet_type ) {
			case QUERY_PACKET : 		pkt_type_str="query";
												break;
			case RESPONSE_PACKET : 	pkt_type_str="response";
												break;
			case CANNOT_CLASSIFY :		err_str="Unable to classify as query or response.";
										pkt_type_str="unknown";
												break;
			default :
												break;
		}
		if ( exception_returned )
			err_str="Exception returned ";
		col_add_fstr(pinfo->cinfo, COL_INFO,
				"%8s [%2u pkt(s)]: trans: %5u; unit: %3u, func: %3u: %s. %s",
				pkt_type_str, 1, mh.transaction_id, (unsigned char) mh.mdbs_hdr.unit_id,
				(unsigned char) mh.mdbs_hdr.function_code, func_string, err_str);
	}

	/* build up protocol tree and iterate over multiple packets */
	packet_num = 0;
	while (1) {
		packet_type = classify_packet(pinfo);
		packet_len = sizeof(mbtcp_hdr) - sizeof(modbus_hdr) + mh.len;

		/* if a tree exists, perform operations to add fields to it */
		if (tree) {
			mi = proto_tree_add_protocol_format(tree, proto_mbtcp, tvb, offset,
					packet_len, "Modbus/TCP");
			mbtcp_tree = proto_item_add_subtree(mi, ett_mbtcp);

			/* Add items to protocol tree specific to Modbus/TCP */
			proto_tree_add_uint(mbtcp_tree, hf_mbtcp_transid, tvb, offset, 2,
					mh.transaction_id);
			proto_tree_add_uint(mbtcp_tree, hf_mbtcp_protid, tvb, offset + 2, 2,
					mh.protocol_id);
			proto_tree_add_uint(mbtcp_tree, hf_mbtcp_len, tvb, offset + 4, 2,
					mh.len);
					
			proto_tree_add_uint(mbtcp_tree, hf_mbtcp_unitid, tvb, offset + 6, 1,
					mh.mdbs_hdr.unit_id);


			/* Add items to protocol tree specific to Modbus generic */
			mf = proto_tree_add_text(mbtcp_tree, tvb, offset + 7, mh.len - 1,
					"Modbus");
	  		modbus_tree = proto_item_add_subtree(mf, ett_modbus_hdr);
			mi = proto_tree_add_uint(modbus_tree, hf_mbtcp_functioncode, tvb, offset + 7, 1,
					mh.mdbs_hdr.function_code);
					
			/** detail payload as a function of exception/function code */
			func_string = val_to_str(mh.mdbs_hdr.function_code,
			    function_code_vals, "Unknown function");
			payload_start = offset + 8;
			payload_len = mh.len - sizeof(modbus_hdr);
			if (exception_returned) {
				proto_item_set_text(mi, "function %u:  %s.  Exception: %s",
						mh.mdbs_hdr.function_code,
						func_string,
						val_to_str(exception_code,
						    exception_code_vals,
						    "Unknown exception code (%u)"));
				proto_tree_add_uint(modbus_tree, hf_modbus_exceptioncode, tvb, payload_start, 1,
						exception_code);
			}
			else {
				proto_item_set_text(mi, "function %u:  %s", mh.mdbs_hdr.function_code,
						func_string);
				switch (mh.mdbs_hdr.function_code) {
					
					case READ_COILS:			
					case READ_INPUT_DISCRETES:	
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_bitcnt, tvb, payload_start + 2, 2, FALSE);
						}
						else if (packet_type == RESPONSE_PACKET) {
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1, byte_cnt);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 1, byte_cnt, "Data");
						}
						break;
						
					case READ_MULT_REGS:		
					case READ_INPUT_REGS:		
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE);
						}
						else if (packet_type == RESPONSE_PACKET) {
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1, byte_cnt);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 1, byte_cnt, "Data");
						}
						break;
						
					case WRITE_COIL:			
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 1, "Data");
							proto_tree_add_text(modbus_tree, tvb, payload_start + 3, 1, "Padding");
						}
						else if (packet_type == RESPONSE_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 1, "Data");
							proto_tree_add_text(modbus_tree, tvb, payload_start + 3, 1, "Padding");
						}
						break;
						
					case WRITE_SINGLE_REG:		
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 2, "Data");
						}
						else if (packet_type == RESPONSE_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 2, 2, "Data");
						}
						break;
						
					case READ_EXCEPT_STAT:		
						if (packet_type == RESPONSE_PACKET)
							proto_tree_add_text(modbus_tree, tvb, payload_start, 1, "Data");
						break;
						
					case FORCE_MULT_COILS:		
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_bitcnt, tvb, payload_start + 2, 2, FALSE);
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start + 4);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start + 4, 1,
									byte_cnt);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 5, byte_cnt, "Data");
						}
						else if (packet_type == RESPONSE_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_bitcnt, tvb, payload_start + 2, 2, FALSE);
						}
						break;
						
					case WRITE_MULT_REGS:		
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE);
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start + 4);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start + 4, 1,
									byte_cnt);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 5, byte_cnt, "Data");
						}
						else if (packet_type == RESPONSE_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE);
						}
						break;
						
					case READ_GENL_REF:			
						if (packet_type == QUERY_PACKET) {
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1,
									byte_cnt);
									
							/* add subtrees to describe each group of packet */
							group_offset = payload_start + 1;
							for (i = 0; i < byte_cnt / 7; i++) {
								mi = proto_tree_add_text( modbus_tree, tvb, group_offset, 7,
										"Group %u", i);
						  		group_tree = proto_item_add_subtree(mi, ett_group_hdr);
								proto_tree_add_item(group_tree, hf_modbus_reftype, tvb, group_offset, 1, FALSE);
								proto_tree_add_item(group_tree, hf_modbus_lreference, tvb, group_offset + 1, 4, FALSE);
								proto_tree_add_item(group_tree, hf_modbus_wordcnt, tvb, group_offset + 5, 2, FALSE);
								group_offset += 7;
							}
						}
						else if (packet_type == RESPONSE_PACKET) {
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1,
									byte_cnt);
									
							/* add subtrees to describe each group of packet */
							group_offset = payload_start + 1;
							i = 0;
							while (byte_cnt > 0) {
								group_byte_cnt = (guint32)tvb_get_guint8(tvb, group_offset);
								mi = proto_tree_add_text( modbus_tree, tvb, group_offset, group_byte_cnt + 1,
										"Group %u", i);
						  		group_tree = proto_item_add_subtree(mi, ett_group_hdr);
								proto_tree_add_uint(group_tree, hf_modbus_bytecnt, tvb, group_offset, 1,
										group_byte_cnt);
								proto_tree_add_item(group_tree, hf_modbus_reftype, tvb, group_offset + 1, 1, FALSE);
								proto_tree_add_text(group_tree, tvb, group_offset + 2, group_byte_cnt - 1, "Data");
								group_offset += (group_byte_cnt + 1);
								byte_cnt -= (group_byte_cnt + 1);
								i++;
							}
						}
						break;
						
					case WRITE_GENL_REF:		
						if ((packet_type == QUERY_PACKET) || (packet_type == RESPONSE_PACKET)) {
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1,
									byte_cnt);
									
							/* add subtrees to describe each group of packet */
							group_offset = payload_start + 1;
							i = 0;
							while (byte_cnt > 0) {
								group_word_cnt = tvb_get_ntohs(tvb, group_offset + 5);
								group_byte_cnt = (2 * group_word_cnt) + 7;
								mi = proto_tree_add_text( modbus_tree, tvb, group_offset, 
										group_byte_cnt, "Group %u", i);
						  		group_tree = proto_item_add_subtree(mi, ett_group_hdr);
								proto_tree_add_item(group_tree, hf_modbus_reftype, tvb, group_offset, 1, FALSE);
								proto_tree_add_item(group_tree, hf_modbus_lreference, tvb, group_offset + 1, 4, FALSE);
								proto_tree_add_uint(group_tree, hf_modbus_wordcnt, tvb, group_offset + 5, 2, 
										group_word_cnt);
								proto_tree_add_text(group_tree, tvb, group_offset + 7, group_byte_cnt - 7, "Data");
								group_offset += group_byte_cnt;
								byte_cnt -= group_byte_cnt;
								i++;
							}
						}
						break;
						
					case MASK_WRITE_REG:		
						if ((packet_type == QUERY_PACKET) || (packet_type == RESPONSE_PACKET)) {
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_andmask, tvb, payload_start + 2, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_ormask, tvb, payload_start + 4, 2, FALSE);
						}
						break;
						
					case READ_WRITE_REG:		
						if (packet_type == QUERY_PACKET) {
							proto_tree_add_item(modbus_tree, hf_modbus_readref, tvb, payload_start, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_readwordcnt, tvb, payload_start + 2, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_writeref, tvb, payload_start + 4, 2, FALSE);
							proto_tree_add_item(modbus_tree, hf_modbus_writewordcnt, tvb, payload_start + 6, 2, FALSE);
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start + 8);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start + 8, 1,
									byte_cnt);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 9, byte_cnt, "Data");
						}
						else if (packet_type == RESPONSE_PACKET) {
							byte_cnt = (guint32)tvb_get_guint8(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_bytecnt, tvb, payload_start, 1,
									byte_cnt);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 1, byte_cnt, "Data");
						}
						break;
						
					case READ_FIFO_QUEUE:		
						if (packet_type == QUERY_PACKET)
							proto_tree_add_item(modbus_tree, hf_modbus_reference, tvb, payload_start, 2, FALSE);
						else if (packet_type == RESPONSE_PACKET) {
							byte_cnt = (guint32)tvb_get_ntohs(tvb, payload_start);
							proto_tree_add_uint(modbus_tree, hf_modbus_lbytecnt, tvb, payload_start, 2,
									byte_cnt);
							proto_tree_add_item(modbus_tree, hf_modbus_wordcnt, tvb, payload_start + 2, 2, FALSE);
							proto_tree_add_text(modbus_tree, tvb, payload_start + 4, byte_cnt - 2, "Data");
						}
						break;
						
					case DIAGNOSTICS:			
					case PROGRAM_484:			
					case POLL_484:				
					case GET_COMM_EVENT_CTRS:	
					case GET_COMM_EVENT_LOG:	
					case PROGRAM_584_984:		
					case POLL_584_984:			
					case REPORT_SLAVE_ID:		
					case PROGRAM_884_U84:		
					case RESET_COMM_LINK:		
					case PROGRAM_CONCEPT:		
					case FIRMWARE_REPLACE:		
					case PROGRAM_584_984_2:		
					case REPORT_LOCAL_ADDR_MB:	
						/* these function codes are not part of the Modbus/TCP specification */
					default:					
						if (payload_len > 0)
							proto_tree_add_text(modbus_tree, tvb, payload_start, payload_len, "Data");
						break;
				}
			}
		}
		
		/* move onto next packet (if there) */
		offset += packet_len;
		packet_num++;
		if (tvb_reported_length_remaining(tvb, offset) > 0) {
			
			/* load header structure for next packet */
			mh.transaction_id = tvb_get_ntohs(tvb, offset+0);
			mh.protocol_id = tvb_get_ntohs(tvb, offset+2);
			mh.len = tvb_get_ntohs(tvb, offset+4);
			mh.mdbs_hdr.unit_id = tvb_get_guint8(tvb, offset+6);
			mh.mdbs_hdr.function_code = tvb_get_guint8(tvb, offset+7);

	
			if ( mh.mdbs_hdr.function_code & 0x80 ) {
				exception_code = tvb_get_guint8(tvb, offset + sizeof(mbtcp_hdr));
				mh.mdbs_hdr.function_code ^= 0x80;
				exception_returned = TRUE;
			} else
				exception_returned = FALSE;
		}
		else
			break;
	}

	return tvb_length(tvb);
}
/* Code to actually dissect the packets */
static void
dissect_cmpp_tcp_pdu(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 *cmpp_tree;
	guint command_id;
	guint tvb_len;
	guint total_length;
	const gchar *command_str; /* Header command string */

	/* Get the length of the PDU */
	tvb_len = tvb_length(tvb);
	/* if the length of the tvb is shorder then the cmpp header length exit */
	if (tvb_len < CMPP_FIX_HEADER_LENGTH)
		return;

	total_length = tvb_get_ntohl(tvb, 0); /* Get the pdu length */
	command_id = tvb_get_ntohl(tvb, 4); /* get the pdu command id */

	if (match_strval(command_id, vals_command_Id) == NULL)
	{
		/* Should never happen: we checked this in dissect_cmpp() */
		return;
	}

	command_str = val_to_str(command_id, vals_command_Id,
				 "(Unknown CMPP Operation 0x%08X)");

	/* tvb has less data then the PDU Header status, return */
	if (tvb_len < total_length)
	{
		/* Should never happen: TCP should have desegmented for us */
		return;
	}

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

	col_append_fstr(pinfo->cinfo, COL_INFO, "%s. ", command_str);

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

		cmpp_tree = proto_item_add_subtree(ti, ett_cmpp);

		/* Add the fix header informations to the tree */
		cmpp_uint4(cmpp_tree, tvb, hf_cmpp_Total_Length, 0);
		cmpp_uint4(cmpp_tree, tvb, hf_cmpp_Command_Id, 4);
		cmpp_uint4(cmpp_tree, tvb, hf_cmpp_Sequence_Id, 8);

		switch(command_id)
		{
			case CMPP_CONNECT:
				cmpp_connect(cmpp_tree, tvb);
				break;
			case CMPP_CONNECT_RESP:
				cmpp_connect_resp(cmpp_tree, tvb);
				break;
			/* CMPP_TERMINATE and CMPP_TERMINATE_RESP don't have msg body */
			case CMPP_TERMINATE:
			case CMPP_TERMINATE_RESP:
				break;
			case CMPP_SUBMIT:
				cmpp_submit(cmpp_tree, tvb);
				break;
			case CMPP_SUBMIT_RESP:
				cmpp_submit_resp(cmpp_tree, tvb);
				break;
			case CMPP_DELIVER:
				cmpp_deliver(cmpp_tree, tvb);
				break;
			case CMPP_DELIVER_RESP:
				cmpp_deliver_resp(cmpp_tree, tvb);
				break;
			default:
				/* Implement the rest of the protocol here */
				break;
		}
	}
}
Beispiel #25
0
static int
dissect_aodv(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item *ti = NULL;
    proto_tree *aodv_tree = NULL;
    gboolean is_ipv6;
    guint8 type;

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

    col_clear(pinfo->cinfo, COL_INFO);

    /* Is this running over IPv6? */
    is_ipv6 = (pinfo->src.type == AT_IPv6);

    /* Check the type of AODV packet. */
    type = tvb_get_guint8(tvb, 0);
    if (match_strval(type, type_vals) == NULL) {
	/*
	 * We assume this is not an AODV packet.
	 */
	return 0;
    }


    col_add_str(pinfo->cinfo, COL_INFO,
                val_to_str(type, type_vals,
                           "Unknown AODV Packet Type (%u)"));
    if (tree) {
	ti = proto_tree_add_protocol_format(tree, proto_aodv, tvb, 0, -1,
	    "Ad hoc On-demand Distance Vector Routing Protocol, %s",
	    val_to_str(type, type_vals, "Unknown AODV Packet Type (%u)"));
	aodv_tree = proto_item_add_subtree(ti, ett_aodv);

	proto_tree_add_uint(aodv_tree, hf_aodv_type, tvb, 0, 1, type);
    }

    switch (type) {
    case RREQ:
	dissect_aodv_rreq(tvb, pinfo, aodv_tree, ti, is_ipv6);
	break;
    case RREP:
	dissect_aodv_rrep(tvb, pinfo, aodv_tree, ti, is_ipv6);
	break;
    case RERR:
	dissect_aodv_rerr(tvb, pinfo, aodv_tree, is_ipv6);
	break;
    case RREP_ACK:
	break;
    case DRAFT_01_V6_RREQ:
	dissect_aodv_draft_01_v6_rreq(tvb, pinfo, aodv_tree, ti);
	break;
    case DRAFT_01_V6_RREP:
	dissect_aodv_draft_01_v6_rrep(tvb, pinfo, aodv_tree, ti);
	break;
    case DRAFT_01_V6_RERR:
	dissect_aodv_draft_01_v6_rerr(tvb, pinfo, aodv_tree);
	break;
    case DRAFT_01_V6_RREP_ACK:
	break;
    default:
	proto_tree_add_text(aodv_tree, tvb, 0, -1,
			    "Unknown AODV Packet Type (%u)", type);
    }

    return tvb_length(tvb);
}
static void
dissect_aarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
  guint16     ar_hrd;
  guint16     ar_pro;
  guint8      ar_hln;
  guint8      ar_pln;
  guint16     ar_op;
  proto_tree  *aarp_tree;
  proto_item  *ti;
  const gchar *op_str;
  int         sha_offset, spa_offset, tha_offset, tpa_offset;
  const guint8      *sha_val, *spa_val, *tha_val, *tpa_val;
  gchar       *sha_str, *spa_str, *tha_str, *tpa_str;

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

  ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
  ar_pro = tvb_get_ntohs(tvb, AR_PRO);
  ar_hln = tvb_get_guint8(tvb, AR_HLN);
  ar_pln = tvb_get_guint8(tvb, AR_PLN);
  ar_op  = tvb_get_ntohs(tvb, AR_OP);

  /* Get the offsets of the addresses. */
  sha_offset = MIN_AARP_HEADER_SIZE;
  spa_offset = sha_offset + ar_hln;
  tha_offset = spa_offset + ar_pln;
  tpa_offset = tha_offset + ar_hln;

  /* Extract the addresses.  */
  sha_val = tvb_get_ptr(tvb, sha_offset, ar_hln);
  sha_str = aarphrdaddr_to_str(sha_val, ar_hln, ar_hrd);

  spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
  spa_str = aarpproaddr_to_str(spa_val, ar_pln, ar_pro);

  tha_val = tvb_get_ptr(tvb, tha_offset, ar_hln);
  tha_str = aarphrdaddr_to_str(tha_val, ar_hln, ar_hrd);

  tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);
  tpa_str = aarpproaddr_to_str(tpa_val, ar_pln, ar_pro);

  switch (ar_op) {
    case AARP_REQUEST:
    case AARP_REQUEST_SWAPPED:
      col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s", tpa_str, spa_str);
      break;
    case AARP_REPLY:
    case AARP_REPLY_SWAPPED:
      col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s", spa_str, sha_str);
      break;
    case AARP_PROBE:
    case AARP_PROBE_SWAPPED:
      col_add_fstr(pinfo->cinfo, COL_INFO, "Is there a %s", tpa_str);
      break;
    default:
      col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown AARP opcode 0x%04x", ar_op);
      break;
  }

  if (tree) {
    if ((op_str = match_strval(ar_op, op_vals)))
      ti = proto_tree_add_protocol_format(tree, proto_aarp, tvb, 0,
				      MIN_AARP_HEADER_SIZE + 2*ar_hln +
				      2*ar_pln, "AppleTalk Address Resolution Protocol (%s)", op_str);
    else
      ti = proto_tree_add_protocol_format(tree, proto_aarp, tvb, 0,
				      MIN_AARP_HEADER_SIZE + 2*ar_hln +
				      2*ar_pln,
				      "AppleTalk Address Resolution Protocol (opcode 0x%04x)", ar_op);
    aarp_tree = proto_item_add_subtree(ti, ett_aarp);
    proto_tree_add_uint(aarp_tree, hf_aarp_hard_type, tvb, AR_HRD, 2,
			       ar_hrd);
    proto_tree_add_uint(aarp_tree, hf_aarp_proto_type, tvb, AR_PRO, 2,
			       ar_pro);
    proto_tree_add_uint(aarp_tree, hf_aarp_hard_size, tvb, AR_HLN, 1,
			       ar_hln);
    proto_tree_add_uint(aarp_tree, hf_aarp_proto_size, tvb, AR_PLN, 1,
			       ar_pln);
    proto_tree_add_uint(aarp_tree, hf_aarp_opcode, tvb, AR_OP, 2,
			       ar_op);
    if (ar_hln != 0) {
      proto_tree_add_item(aarp_tree,
	AARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_aarp_src_hw_mac : hf_aarp_src_hw,
	tvb, sha_offset, ar_hln, FALSE);
    }

    if (ar_pln != 0) {
      if (AARP_PRO_IS_ATALK(ar_pro, ar_pln)) {
        proto_tree_add_bytes_format_value(aarp_tree, hf_aarp_src_proto_id, tvb,
					  spa_offset, ar_pln,
					  spa_val,
					  "%s", spa_str);
      } else {
        proto_tree_add_bytes_format_value(aarp_tree, hf_aarp_src_proto, tvb,
					  spa_offset, ar_pln,
					  spa_val,
					  "%s", spa_str);
      }
    }

    if (ar_hln != 0) {
      proto_tree_add_item(aarp_tree,
	AARP_HW_IS_ETHER(ar_hrd, ar_hln) ? hf_aarp_dst_hw_mac : hf_aarp_dst_hw,
	tvb, tha_offset, ar_hln, FALSE);
    }

    if (ar_pln != 0) {
      if (AARP_PRO_IS_ATALK(ar_pro, ar_pln)) {
        proto_tree_add_bytes_format_value(aarp_tree, hf_aarp_dst_proto_id, tvb,
					  tpa_offset, ar_pln,
					  tpa_val,
					  "%s", tpa_str);
      } else {
        proto_tree_add_bytes_format_value(aarp_tree, hf_aarp_dst_proto, tvb,
					  tpa_offset, ar_pln,
					  tpa_val,
					  "%s", tpa_str);
      }
    }
  }
}
Beispiel #27
0
static int
dissect_slimp3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    const char		*opcode_str;
    proto_tree		*slimp3_tree = NULL;
    proto_item		*ti = NULL, *hidden_item;
    gint		i1;
    gint		offset = 0;
    guint16		opcode;
    guchar		lcd_char;
    char		lcd_str[MAX_LCD_STR_LEN + 1];
    int			to_server = FALSE;
    int			old_protocol = FALSE;
    address		tmp_addr;
    gboolean		in_str;
    int			lcd_strlen;

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

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

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

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

    }

    if (tree) {

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

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

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

    switch (opcode) {

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

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

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

    case SLIMP3_DISPLAY:
        if (tree) {

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

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

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

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

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

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

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

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

        break;

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

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

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

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

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

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

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

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

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

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

        if (check_col(pinfo->cinfo, COL_INFO)) {
            guint8 fw_ver = tvb_get_guint8(tvb, offset+2);
            col_append_fstr(pinfo->cinfo, COL_INFO, ", Device ID: %d. Firmware: %d.%d",
                            tvb_get_guint8(tvb, offset+1), fw_ver>>4, fw_ver & 0xf);
        }
Beispiel #28
0
/*
 * RFC 2225 ATMARP - it's just like ARP, except where it isn't.
 */
static void
dissect_atmarp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint16     ar_hrd;
  guint16     ar_pro;
  guint8      ar_shtl;
  guint8      ar_shl;
  guint8      ar_sstl;
  guint8      ar_ssl;
  guint16     ar_op;
  guint8      ar_spln;
  guint8      ar_thtl;
  guint8      ar_thl;
  guint8      ar_tstl;
  guint8      ar_tsl;
  guint8      ar_tpln;
  int         tot_len;
  proto_tree  *arp_tree;
  proto_item  *ti;
  const gchar *op_str;
  int         sha_offset, ssa_offset, spa_offset;
  int         tha_offset, tsa_offset, tpa_offset;
  const guint8      *sha_val, *ssa_val, *spa_val;
  const guint8      *tha_val, *tsa_val, *tpa_val;
  const gchar       *sha_str, *ssa_str, *spa_str;
  const gchar       *tha_str, *tsa_str, *tpa_str;
  proto_tree  *tl_tree;
  proto_item  *tl;

  /* Override the setting to "ARP/RARP". */
  pinfo->current_proto = "ATMARP";

  ar_hrd = tvb_get_ntohs(tvb, ATM_AR_HRD);
  ar_pro = tvb_get_ntohs(tvb, ATM_AR_PRO);
  ar_shtl = tvb_get_guint8(tvb, ATM_AR_SHTL);
  ar_shl = ar_shtl & ATMARP_LEN_MASK;
  ar_sstl = tvb_get_guint8(tvb, ATM_AR_SSTL);
  ar_ssl = ar_sstl & ATMARP_LEN_MASK;
  ar_op  = tvb_get_ntohs(tvb, AR_OP);
  ar_spln = tvb_get_guint8(tvb, ATM_AR_SPLN);
  ar_thtl = tvb_get_guint8(tvb, ATM_AR_THTL);
  ar_thl = ar_thtl & ATMARP_LEN_MASK;
  ar_tstl = tvb_get_guint8(tvb, ATM_AR_TSTL);
  ar_tsl = ar_tstl & ATMARP_LEN_MASK;
  ar_tpln = tvb_get_guint8(tvb, ATM_AR_TPLN);

  tot_len = MIN_ATMARP_HEADER_SIZE + ar_shl + ar_ssl + ar_spln +
    ar_thl + ar_tsl + ar_tpln;

  /* Adjust the length of this tvbuff to include only the ARP datagram.
     Our caller may use that to determine how much of its packet
     was padding. */
  tvb_set_reported_length(tvb, tot_len);

  /* Extract the addresses.  */
  sha_offset = MIN_ATMARP_HEADER_SIZE;
  if (ar_shl != 0) {
    sha_val = tvb_get_ptr(tvb, sha_offset, ar_shl);
    sha_str = atmarpnum_to_str(sha_val, ar_shtl);
  } else {
    sha_val = NULL;
    sha_str = "<No address>";
  }

  ssa_offset = sha_offset + ar_shl;
  if (ar_ssl != 0) {
    ssa_val = tvb_get_ptr(tvb, ssa_offset, ar_ssl);
    ssa_str = atmarpsubaddr_to_str(ssa_val, ar_sstl);
  } else {
    ssa_val = NULL;
    ssa_str = NULL;
  }

  spa_offset = ssa_offset + ar_ssl;
  spa_val = tvb_get_ptr(tvb, spa_offset, ar_spln);
  spa_str = arpproaddr_to_str(spa_val, ar_spln, ar_pro);

  tha_offset = spa_offset + ar_spln;
  if (ar_thl != 0) {
    tha_val = tvb_get_ptr(tvb, tha_offset, ar_thl);
    tha_str = atmarpnum_to_str(tha_val, ar_thtl);
  } else {
    tha_val = NULL;
    tha_str = "<No address>";
  }

  tsa_offset = tha_offset + ar_thl;
  if (ar_tsl != 0) {
    tsa_val = tvb_get_ptr(tvb, tsa_offset, ar_tsl);
    tsa_str = atmarpsubaddr_to_str(tsa_val, ar_tstl);
  } else {
    tsa_val = NULL;
    tsa_str = NULL;
  }

  tpa_offset = tsa_offset + ar_tsl;
  tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_tpln);
  tpa_str = arpproaddr_to_str(tpa_val, ar_tpln, ar_pro);

  if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
    switch (ar_op) {

      case ARPOP_REQUEST:
      case ARPOP_REPLY:
      case ATMARPOP_NAK:
      default:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMARP");
        break;

      case ARPOP_RREQUEST:
      case ARPOP_RREPLY:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "ATMRARP");
        break;

      case ARPOP_IREQUEST:
      case ARPOP_IREPLY:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ATMARP");
        break;
    }
  }

  if (check_col(pinfo->cinfo, COL_INFO)) {
    switch (ar_op) {
      case ARPOP_REQUEST:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s",
                     tpa_str, spa_str);
        break;
      case ARPOP_REPLY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s%s%s", spa_str, sha_str,
                     ((ssa_str != NULL) ? "," : ""),
                     ((ssa_str != NULL) ? ssa_str : ""));
        break;
      case ARPOP_IREQUEST:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s%s%s?  Tell %s%s%s",
                     tha_str,
                     ((tsa_str != NULL) ? "," : ""),
                     ((tsa_str != NULL) ? tsa_str : ""),
                     sha_str,
                     ((ssa_str != NULL) ? "," : ""),
                     ((ssa_str != NULL) ? ssa_str : ""));
        break;
      case ARPOP_IREPLY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s%s%s is at %s",
                     sha_str,
                     ((ssa_str != NULL) ? "," : ""),
                     ((ssa_str != NULL) ? ssa_str : ""),
                     spa_str);
        break;
      case ATMARPOP_NAK:
        col_add_fstr(pinfo->cinfo, COL_INFO, "I don't know where %s is", spa_str);
        break;
      default:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ATMARP opcode 0x%04x", ar_op);
        break;
    }
  }

  if (tree) {
    if ((op_str = match_strval(ar_op, atmop_vals)))
      ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
                                          "ATM Address Resolution Protocol (%s)",
                                          op_str);
    else
      ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
                                          "ATM Address Resolution Protocol (opcode 0x%04x)", ar_op);
    arp_tree = proto_item_add_subtree(ti, ett_arp);

    proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, ATM_AR_HRD, 2, ar_hrd);

    proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, ATM_AR_PRO, 2,ar_pro);

    tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SHTL, 1,
                             "Sender ATM number type/length: %s/%u",
                             (ar_shtl & ATMARP_IS_E164 ?
                              "E.164" :
                              "ATM Forum NSAPA"),
                             ar_shl);
    tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
    proto_tree_add_boolean(tl_tree, hf_atmarp_sht, tvb, ATM_AR_SHTL, 1, ar_shtl);
    proto_tree_add_uint(tl_tree, hf_atmarp_shl, tvb, ATM_AR_SHTL, 1, ar_shtl);

    tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_SSTL, 1,
                             "Sender ATM subaddress type/length: %s/%u",
                             (ar_sstl & ATMARP_IS_E164 ?
                              "E.164" :
                              "ATM Forum NSAPA"),
                             ar_ssl);
    tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
    proto_tree_add_boolean(tl_tree, hf_atmarp_sst, tvb, ATM_AR_SSTL, 1, ar_sstl);
    proto_tree_add_uint(tl_tree, hf_atmarp_ssl, tvb, ATM_AR_SSTL, 1, ar_sstl);

    proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP,  2, ar_op);


    proto_tree_add_uint(arp_tree, hf_atmarp_spln, tvb, ATM_AR_SPLN, 1, ar_spln);

    tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_THTL, 1,
                             "Target ATM number type/length: %s/%u",
                             (ar_thtl & ATMARP_IS_E164 ?
                              "E.164" :
                              "ATM Forum NSAPA"),
                             ar_thl);
    tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
    proto_tree_add_boolean(tl_tree, hf_atmarp_tht, tvb, ATM_AR_THTL, 1, ar_thtl);
    proto_tree_add_uint(tl_tree, hf_atmarp_thl, tvb, ATM_AR_THTL, 1, ar_thtl);

    tl = proto_tree_add_text(arp_tree, tvb, ATM_AR_TSTL, 1,
                             "Target ATM subaddress type/length: %s/%u",
                             (ar_tstl & ATMARP_IS_E164 ?
                              "E.164" :
                              "ATM Forum NSAPA"),
                             ar_tsl);
    tl_tree = proto_item_add_subtree(tl, ett_atmarp_tl);
    proto_tree_add_boolean(tl_tree, hf_atmarp_tst, tvb, ATM_AR_TSTL, 1, ar_tstl);
    proto_tree_add_uint(tl_tree, hf_atmarp_tsl, tvb, ATM_AR_TSTL, 1, ar_tstl);

    proto_tree_add_uint(arp_tree, hf_atmarp_tpln, tvb, ATM_AR_TPLN, 1, ar_tpln);

    if (ar_shl != 0)
      dissect_atm_number(tvb, sha_offset, ar_shtl, hf_atmarp_src_atm_num_e164,
                         hf_atmarp_src_atm_num_nsap, arp_tree);

    if (ar_ssl != 0)
      proto_tree_add_bytes_format(arp_tree, hf_atmarp_src_atm_subaddr, tvb, ssa_offset,
                                  ar_ssl,
                                  ssa_val,
                                  "Sender ATM subaddress: %s", ssa_str);

    if (ar_spln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_PRO_IS_IPv4(ar_pro, ar_spln) ? hf_arp_src_proto_ipv4
                          : hf_arp_src_proto,
                          tvb, spa_offset, ar_spln, FALSE);
    }

    if (ar_thl != 0)
      dissect_atm_number(tvb, tha_offset, ar_thtl, hf_atmarp_dst_atm_num_e164,
                         hf_atmarp_dst_atm_num_nsap, arp_tree);

    if (ar_tsl != 0)
      proto_tree_add_bytes_format(arp_tree, hf_atmarp_dst_atm_subaddr, tvb, tsa_offset,
                                  ar_tsl,
                                  tsa_val,
                                  "Target ATM subaddress: %s", tsa_str);

    if (ar_tpln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_PRO_IS_IPv4(ar_pro, ar_tpln) ? hf_arp_dst_proto_ipv4
                          : hf_arp_dst_proto,
                          tvb, tpa_offset, ar_tpln, FALSE);
    }
  }
}
Beispiel #29
0
static void
dissect_arp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  guint16     ar_hrd;
  guint16     ar_pro;
  guint8      ar_hln;
  guint8      ar_pln;
  guint16     ar_op;
  int         tot_len;
  proto_tree  *arp_tree = NULL;
  proto_item  *ti, *item;
  const gchar *op_str;
  int         sha_offset, spa_offset, tha_offset, tpa_offset;
  const guint8      *spa_val, *tpa_val;
  gboolean    is_gratuitous;
  gboolean    duplicate_detected = FALSE;
  guint32     duplicate_ip = 0;

  /* Call it ARP, for now, so that if we throw an exception before
     we decide whether it's ARP or RARP or IARP or ATMARP, it shows
     up in the packet list as ARP.

     Clear the Info column so that, if we throw an exception, it
     shows up as a short or malformed ARP frame. */
  col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
  col_clear(pinfo->cinfo, COL_INFO);

  /* Hardware Address Type */
  ar_hrd = tvb_get_ntohs(tvb, AR_HRD);
  if (ar_hrd == ARPHRD_ATM2225) {
    call_dissector(atmarp_handle, tvb, pinfo, tree);
    return;
  }
  /* Protocol Address Type */
  ar_pro = tvb_get_ntohs(tvb, AR_PRO);
  /* Hardware Address Size */
  ar_hln = tvb_get_guint8(tvb, AR_HLN);
  /* Protocol Address Size */
  ar_pln = tvb_get_guint8(tvb, AR_PLN);
  /* Operation */
  ar_op  = tvb_get_ntohs(tvb, AR_OP);

  tot_len = MIN_ARP_HEADER_SIZE + ar_hln*2 + ar_pln*2;

  /* Adjust the length of this tvbuff to include only the ARP datagram.
     Our caller may use that to determine how much of its packet
     was padding. */
  tvb_set_reported_length(tvb, tot_len);

  if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
    switch (ar_op) {

      case ARPOP_REQUEST:
        if (global_arp_detect_request_storm)
        {
          request_seen(pinfo);
        }
	/* FALLTHRU */
      case ARPOP_REPLY:
      default:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "ARP");
        break;

      case ARPOP_RREQUEST:
      case ARPOP_RREPLY:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "RARP");
        break;

      case ARPOP_IREQUEST:
      case ARPOP_IREPLY:
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "Inverse ARP");
        break;
    }
  }

  /* Get the offsets of the addresses. */
  /* Source Hardware Address */
  sha_offset = MIN_ARP_HEADER_SIZE;
  /* Source Protocol Address */
  spa_offset = sha_offset + ar_hln;
  /* Target Hardware Address */
  tha_offset = spa_offset + ar_pln;
  /* Target Protocol Address */
  tpa_offset = tha_offset + ar_hln;

  if ((ar_op == ARPOP_REPLY || ar_op == ARPOP_REQUEST) &&
      ARP_HW_IS_ETHER(ar_hrd, ar_hln) &&
      ARP_PRO_IS_IPv4(ar_pro, ar_pln)) {

    /* inform resolv.c module of the new discovered addresses */

    guint32 ip;
    const guint8 *mac;

    /* Add sender address if sender MAC address is neither a broadcast/
       multicast address nor an all-zero address and if sender IP address
       isn't all zeroes. */
    ip = tvb_get_ipv4(tvb, spa_offset);
    mac = tvb_get_ptr(tvb, sha_offset, 6);
    if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0)
    {
      add_ether_byip(ip, mac);
      if (global_arp_detect_duplicate_ip_addresses)
      {
        duplicate_detected =
          check_for_duplicate_addresses(pinfo, tree, tvb, mac, ip,
                                        &duplicate_ip);
      }
    }

    /* Add target address if target MAC address is neither a broadcast/
       multicast address nor an all-zero address and if target IP address
       isn't all zeroes. */

    /* Do not add target address if the packet is a Request. According to the RFC,
       target addresses in requests have no meaning */

    ip = tvb_get_ipv4(tvb, tpa_offset);
    mac = tvb_get_ptr(tvb, tha_offset, 6);
    if ((mac[0] & 0x01) == 0 && memcmp(mac, mac_allzero, 6) != 0 && ip != 0
        && ar_op != ARPOP_REQUEST)
    {
      add_ether_byip(ip, mac);
      if (global_arp_detect_duplicate_ip_addresses)
      {
        duplicate_detected =
          check_for_duplicate_addresses(pinfo, tree, tvb, mac, ip,
                                        &duplicate_ip);
      }
    }
  }

  if (!tree && !check_col(pinfo->cinfo, COL_INFO)) {
    /* We're not building a protocol tree and we're not setting the Info
       column, so we don't have any more work to do. */
    return;
  }

  spa_val = tvb_get_ptr(tvb, spa_offset, ar_pln);
  tpa_val = tvb_get_ptr(tvb, tpa_offset, ar_pln);

  /* ARP requests/replies with the same sender and target protocol
     address are flagged as "gratuitous ARPs", i.e. ARPs sent out as,
     in effect, an announcement that the machine has MAC address
     XX:XX:XX:XX:XX:XX and IPv4 address YY.YY.YY.YY. Requests are to
     provoke complaints if some other machine has the same IPv4 address,
     replies are used to announce relocation of network address, like
     in failover solutions. */
  if (((ar_op == ARPOP_REQUEST) || (ar_op == ARPOP_REPLY)) && (memcmp(spa_val, tpa_val, ar_pln) == 0))
    is_gratuitous = TRUE;
  else
    is_gratuitous = FALSE;

  if (check_col(pinfo->cinfo, COL_INFO)) {
    switch (ar_op) {
      case ARPOP_REQUEST:
	if (is_gratuitous)
          col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Request)",
                       arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
	else
          col_add_fstr(pinfo->cinfo, COL_INFO, "Who has %s?  Tell %s",
                       arpproaddr_to_str(tpa_val, ar_pln, ar_pro),
                       arpproaddr_to_str(spa_val, ar_pln, ar_pro));
        break;
      case ARPOP_REPLY:
        if (is_gratuitous)
          col_add_fstr(pinfo->cinfo, COL_INFO, "Gratuitous ARP for %s (Reply)",
                       arpproaddr_to_str(spa_val, ar_pln, ar_pro));
        else
          col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
                       arpproaddr_to_str(spa_val, ar_pln, ar_pro),
                       tvb_arphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd));
        break;
      case ARPOP_RREQUEST:
      case ARPOP_IREQUEST:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Who is %s?  Tell %s",
                     tvb_arphrdaddr_to_str(tvb, tha_offset, ar_hln, ar_hrd),
                     tvb_arphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd));
        break;
      case ARPOP_RREPLY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
                     tvb_arphrdaddr_to_str(tvb, tha_offset, ar_hln, ar_hrd),
                     arpproaddr_to_str(tpa_val, ar_pln, ar_pro));
        break;
      case ARPOP_IREPLY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s is at %s",
                     tvb_arphrdaddr_to_str(tvb, sha_offset, ar_hln, ar_hrd),
                     arpproaddr_to_str(spa_val, ar_pln, ar_pro));
        break;
      default:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown ARP opcode 0x%04x", ar_op);
        break;
    }
  }

  if (tree) {
    if ((op_str = match_strval(ar_op, op_vals)))  {
      if (is_gratuitous && (ar_op == ARPOP_REQUEST))
        op_str = "request/gratuitous ARP";
      if (is_gratuitous && (ar_op == ARPOP_REPLY))
        op_str = "reply/gratuitous ARP";
      ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
                                          "Address Resolution Protocol (%s)", op_str);
    } else
      ti = proto_tree_add_protocol_format(tree, proto_arp, tvb, 0, tot_len,
                                          "Address Resolution Protocol (opcode 0x%04x)", ar_op);
    arp_tree = proto_item_add_subtree(ti, ett_arp);
    proto_tree_add_uint(arp_tree, hf_arp_hard_type, tvb, AR_HRD, 2, ar_hrd);
    proto_tree_add_uint(arp_tree, hf_arp_proto_type, tvb, AR_PRO, 2, ar_pro);
    proto_tree_add_uint(arp_tree, hf_arp_hard_size, tvb, AR_HLN, 1, ar_hln);
    proto_tree_add_uint(arp_tree, hf_arp_proto_size, tvb, AR_PLN, 1, ar_pln);
    proto_tree_add_uint(arp_tree, hf_arp_opcode, tvb, AR_OP,  2, ar_op);
    item = proto_tree_add_boolean(arp_tree, hf_arp_isgratuitous, tvb, 0, 0, is_gratuitous);
    PROTO_ITEM_SET_GENERATED(item);
    if (ar_hln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_HW_IS_ETHER(ar_hrd, ar_hln) ?
                          hf_arp_src_hw_mac :
                          hf_arp_src_hw,
                          tvb, sha_offset, ar_hln, FALSE);
    }
    if (ar_pln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_PRO_IS_IPv4(ar_pro, ar_pln) ?
                          hf_arp_src_proto_ipv4 :
                          hf_arp_src_proto,
                          tvb, spa_offset, ar_pln, FALSE);
    }
    if (ar_hln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_HW_IS_ETHER(ar_hrd, ar_hln) ?
                          hf_arp_dst_hw_mac :
                          hf_arp_dst_hw,
                          tvb, tha_offset, ar_hln, FALSE);
    }
    if (ar_pln != 0) {
      proto_tree_add_item(arp_tree,
                          ARP_PRO_IS_IPv4(ar_pro, ar_pln) ?
                          hf_arp_dst_proto_ipv4 :
                          hf_arp_dst_proto,
                          tvb, tpa_offset, ar_pln, FALSE);
    }
  }

  if (global_arp_detect_request_storm)
  {
    check_for_storm_count(tvb, pinfo, arp_tree);
  }

  if (duplicate_detected)
  {
    /* Also indicate in info column */
    if (check_col(pinfo->cinfo, COL_INFO))
    {
      col_append_fstr(pinfo->cinfo, COL_INFO, " (duplicate use of %s detected!)",
                      arpproaddr_to_str((guint8*)&duplicate_ip, 4, ETHERTYPE_IP));
    }
  }
}
Beispiel #30
0
void
dissect_nmas_reply(tvbuff_t *tvb, packet_info *pinfo, proto_tree *ncp_tree, guint8 func _U_, guint8 subfunc, ncp_req_hash_value *request_value)
{
    guint32             foffset=0, roffset=0;
    guint32             subverb=0;
    guint8              msgverb=0;
    guint32             msg_length=0;
    guint32             return_code=0, encrypt_error=0;
    proto_tree          *atree;
    proto_item          *aitem;
    proto_item          *expert_item;
    const gchar         *str;


    foffset = 8;
    if (request_value) {
        subverb = request_value->req_nds_flags;
        msgverb = request_value->nds_request_verb;
    }
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "NMAS");
    if (tvb_reported_length_remaining(tvb, foffset)<4) {
        return;
    }

    aitem = proto_tree_add_text(ncp_tree, tvb, foffset, -1, "Packet Type: %s",
                                val_to_str(subfunc, nmas_func_enum, "Unknown (0x%02x)"));
    atree = proto_item_add_subtree(aitem, ett_nmas);
    switch (subfunc) {
    case 1:
        proto_tree_add_item(atree, hf_ping_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        foffset += 4;
        proto_tree_add_item(atree, hf_nmas_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        foffset += 4;
        break;
    case 2:
        proto_tree_add_text(atree, tvb, foffset, -1, "Verb: %s",
                            val_to_str(subverb, nmas_subverb_enum, "Unknown (%u)"));
        proto_tree_add_item(atree, hf_length, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        msg_length = tvb_get_letohl(tvb, foffset);
        foffset +=4;
        proto_tree_add_item(atree, hf_frag_handle, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
        /* Check for a fragment packet */
        if (tvb_get_letohl(tvb, foffset)!=0xffffffff) {
            break;
        }
        foffset += 4;
        return_code = tvb_get_letohl(tvb, foffset);
        roffset = foffset;
        foffset += 4;
        msg_length -= 8;
        if (return_code == 0 && msg_length > 0)
        {
            switch (subverb) {
            case 0:             /* Fragmented Ping */
                proto_tree_add_item(atree, hf_ping_flags, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
                foffset += 4;
                proto_tree_add_item(atree, hf_nmas_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
                foffset += 4;
                break;
            case 2:             /* Client Put Data */
                proto_tree_add_item(atree, hf_squeue_bytes, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
                foffset += 4;
                proto_tree_add_item(atree, hf_cqueue_bytes, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
                foffset += 4;
                break;
            case 4:             /* Client Get Data */
                proto_tree_add_item(atree, hf_opaque, tvb, foffset, msg_length, ENC_NA);
                foffset += msg_length;
                break;
            case 6:             /* Client Get User NDS Credentials */
                proto_tree_add_item(atree, hf_num_creds, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
                foffset += 4;
                proto_tree_add_item(atree, hf_cred_type, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
                foffset += 4;
                proto_tree_add_item(atree, hf_login_state, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
                foffset += 4;
                msg_length -= 12;
                proto_tree_add_item(atree, hf_enc_cred, tvb, foffset, msg_length, ENC_NA);
                foffset += msg_length;
                break;
            case 8:             /* Login Store Management */
                proto_tree_add_text(atree, tvb, foffset, -1, "Subverb: %s",
                                    val_to_str(msgverb, nmas_lsmverb_enum, "Unknown (%u)"));
                switch(msgverb)
                {
                    /* The data within these structures is all encrypted. */
                case 1:
                case 3:
                case 5:
                case 7:
                case 9:
                    proto_tree_add_item(atree, hf_enc_data, tvb, foffset, msg_length, ENC_NA);
                    foffset += msg_length;
                    break;
                default:
                    break;
                }
                break;
            case 10:            /* Writable Object Check */
                proto_tree_add_item(atree, hf_nmas_version, tvb, foffset, 4, ENC_LITTLE_ENDIAN);
                foffset += 4;
                break;
            case 1242:          /* Message Handler */
                proto_tree_add_text(atree, tvb, foffset, -1, "Subverb: %s",
                                    val_to_str(msgverb, nmas_msgverb_enum, "Unknown (%u)"));
                switch(msgverb)
                {
                case 1:
                    msg_length = tvb_get_ntohl(tvb, foffset);
                    proto_tree_add_item(atree, hf_length, tvb, foffset, 4, ENC_BIG_ENDIAN);
                    foffset += 4;
                    proto_tree_add_item(atree, hf_data, tvb, foffset, msg_length, ENC_NA);
                    foffset += msg_length;
                    break;
                case 3:
                    proto_tree_add_item(atree, hf_session_ident, tvb, foffset, 4, ENC_BIG_ENDIAN);
                    foffset += 4;
                    break;
                case 5:
                    /* No Op */
                    break;
                case 7:
                    encrypt_error = tvb_get_ntohl(tvb, foffset);
                    str = match_strval(encrypt_error, nmas_errors_enum);
                    if (str)
                    {
                        col_add_fstr(pinfo->cinfo, COL_INFO, "R Payload Error - %s", str);
                        expert_item = proto_tree_add_item(atree, hf_encrypt_error, tvb, foffset, 4, ENC_BIG_ENDIAN);
                        expert_add_info_format(pinfo, expert_item, PI_RESPONSE_CODE, PI_ERROR, "NMAS Payload Error: %s", str);
                    }
                    else
                    {
                        proto_tree_add_item(atree, hf_opaque, tvb, foffset, msg_length, ENC_NA);
                    }
                    foffset += msg_length;
                    break;
                case 9:
                    /* No Op */
                    break;
                default:
                    break;
                }
                break;
            default:
                break;
            }
        }
        str = match_strval(return_code, nmas_errors_enum);
        if (str)
        {
            expert_item = proto_tree_add_item(atree, hf_return_code, tvb, roffset, 4, ENC_LITTLE_ENDIAN);
            expert_add_info_format(pinfo, expert_item, PI_RESPONSE_CODE, PI_ERROR, "NMAS Error: 0x%08x %s", return_code, str);
            col_add_fstr(pinfo->cinfo, COL_INFO, "R Error - %s", str);
        }
        else
        {
            if (return_code!=0)
            {
                expert_item = proto_tree_add_item(atree, hf_return_code, tvb, roffset, 4, ENC_LITTLE_ENDIAN);
                expert_add_info_format(pinfo, expert_item, PI_RESPONSE_CODE, PI_ERROR, "NMAS Error: 0x%08x is unknown", return_code);
                if (check_col(pinfo->cinfo, COL_INFO)) {
                   col_add_fstr(pinfo->cinfo, COL_INFO, "R Unknown NMAS Error - 0x%08x", return_code);
                }
            }
        }

        if (return_code == 0) {
            proto_tree_add_text(atree, tvb, roffset, 4, "Return Code: Success (0x00000000)");
        }
        break;
    case 3:
        break;
    default:
        break;
    }
}