Пример #1
0
static int
dissect_netmon_802_11(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data)
{
  struct ieee_802_11_phdr *phdr = (struct ieee_802_11_phdr *)data;
  proto_tree *wlan_tree = NULL, *opmode_tree;
  proto_item *ti;
  tvbuff_t   *next_tvb;
  int         offset;
  guint8      version;
  guint16     length;
  guint32     phy_type;
  guint32     flags;
  guint32     channel;
  gint        calc_channel;
  gint32      rssi;
  guint8      rate;

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

  version = tvb_get_guint8(tvb, offset);
  length = tvb_get_letohs(tvb, offset+1);
  col_add_fstr(pinfo->cinfo, COL_INFO, "NetMon WLAN Capture v%u, Length %u",
               version, length);
  if (version != 2) {
    /* XXX - complain */
    goto skip;
  }
  if (length < MIN_HEADER_LEN) {
    /* XXX - complain */
    goto skip;
  }

  /* Dissect the packet */
  ti = proto_tree_add_item(tree, proto_netmon_802_11, tvb, 0, length,
                           ENC_NA);
  wlan_tree = proto_item_add_subtree(ti, ett_netmon_802_11);

  /*
   * XXX - is this the NDIS_OBJECT_HEADER structure:
   *
   *    https://msdn.microsoft.com/en-us/library/windows/hardware/ff566588(v=vs.85).aspx
   *
   * at the beginning of a DOT11_EXTSTA_RECV_CONTEXT structure:
   *
   *    https://msdn.microsoft.com/en-us/library/windows/hardware/ff548626(v=vs.85).aspx
   *
   * If so, the byte at an offset of 0 would be the appropriate type for the
   * structure following it, i.e. NDIS_OBJECT_TYPE_DEFAULT.
   */
  proto_tree_add_item(wlan_tree, hf_netmon_802_11_version, tvb, offset, 1,
                      ENC_LITTLE_ENDIAN);
  offset += 1;
  proto_tree_add_item(wlan_tree, hf_netmon_802_11_length, tvb, offset, 2,
                      ENC_LITTLE_ENDIAN);
  offset += 2;

  /*
   * This isn't in the DOT11_EXTSTA_RECV_CONTEXT structure.
   */
  ti = proto_tree_add_item(wlan_tree, hf_netmon_802_11_op_mode, tvb, offset,
                      4, ENC_LITTLE_ENDIAN);
  opmode_tree = proto_item_add_subtree(ti, ett_netmon_802_11_op_mode);
  proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_sta, tvb, offset,
                      4, ENC_LITTLE_ENDIAN);
  proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_ap, tvb, offset,
                      4, ENC_LITTLE_ENDIAN);
  proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_sta_ext, tvb,
                      offset, 4, ENC_LITTLE_ENDIAN);
  proto_tree_add_item(opmode_tree, hf_netmon_802_11_op_mode_mon, tvb, offset,
                      4, ENC_LITTLE_ENDIAN);
  offset += 4;

  /*
   * uReceiveFlags?
   */
  flags = tvb_get_letohl(tvb, offset);
  offset += 4;
  if (flags != 0xffffffff) {
    /*
     * uPhyId?
     */
    phy_type = tvb_get_letohl(tvb, offset);
    memset(&phdr->phy_info, 0, sizeof(phdr->phy_info));

    switch (phy_type) {

    case PHY_TYPE_UNKNOWN:
        phdr->phy = PHDR_802_11_PHY_UNKNOWN;
        break;

    case PHY_TYPE_FHSS:
        phdr->phy = PHDR_802_11_PHY_11_FHSS;
        break;

    case PHY_TYPE_IR_BASEBAND:
        phdr->phy = PHDR_802_11_PHY_11_IR;
        break;

    case PHY_TYPE_DSSS:
        phdr->phy = PHDR_802_11_PHY_11_DSSS;
        break;

    case PHY_TYPE_HR_DSSS:
        phdr->phy = PHDR_802_11_PHY_11B;
        break;

    case PHY_TYPE_OFDM:
        phdr->phy = PHDR_802_11_PHY_11A;
        break;

    case PHY_TYPE_ERP:
        phdr->phy = PHDR_802_11_PHY_11G;
        break;

    case PHY_TYPE_HT:
        phdr->phy = PHDR_802_11_PHY_11N;
        break;

    case PHY_TYPE_VHT:
        phdr->phy = PHDR_802_11_PHY_11AC;
        break;

    default:
        phdr->phy = PHDR_802_11_PHY_UNKNOWN;
        break;
    }
    proto_tree_add_item(wlan_tree, hf_netmon_802_11_phy_type, tvb, offset, 4,
                        ENC_LITTLE_ENDIAN);
    offset += 4;

    /*
     * uChCenterFrequency?
     */
    channel = tvb_get_letohl(tvb, offset);
    if (channel < 1000) {
      if (channel == 0) {
        proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_channel,
                                         tvb, offset, 4, channel,
                                         "Unknown");
      } else {
        guint frequency;

        phdr->has_channel = TRUE;
        phdr->channel = channel;
        proto_tree_add_uint(wlan_tree, hf_netmon_802_11_channel,
                            tvb, offset, 4, channel);
        switch (phdr->phy) {

        case PHDR_802_11_PHY_11B:
        case PHDR_802_11_PHY_11G:
          /* 2.4 GHz channel */
          frequency = ieee80211_chan_to_mhz(channel, TRUE);
          break;

        case PHDR_802_11_PHY_11A:
          /* 5 GHz channel */
          frequency = ieee80211_chan_to_mhz(channel, FALSE);
          break;

        default:
          frequency = 0;
          break;
        }
        if (frequency != 0) {
          phdr->has_frequency = TRUE;
          phdr->frequency = frequency;
        }
      }
    } else {
      phdr->has_frequency = TRUE;
      phdr->frequency = channel;
      proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_frequency,
                                       tvb, offset, 4, channel,
                                       "%u Mhz", channel);
      calc_channel = ieee80211_mhz_to_chan(channel);
      if (calc_channel != -1) {
        phdr->has_channel = TRUE;
        phdr->channel = calc_channel;
      }
    }
    offset += 4;

    /*
     * usNumberOfMPDUsReceived is missing.
     */

    /*
     * lRSSI?
     */
    rssi = tvb_get_letohl(tvb, offset);
    if (rssi == 0) {
      proto_tree_add_int_format_value(wlan_tree, hf_netmon_802_11_rssi,
                                      tvb, offset, 4, rssi,
                                      "Unknown");
    } else {
      phdr->has_signal_dbm = TRUE;
      phdr->signal_dbm = rssi;
      proto_tree_add_int_format_value(wlan_tree, hf_netmon_802_11_rssi,
                                      tvb, offset, 4, rssi,
                                      "%d dBm", rssi);
    }
    offset += 4;

    /*
     * ucDataRate?
     */
    rate = tvb_get_guint8(tvb, offset);
    if (rate == 0) {
      proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_datarate,
                                       tvb, offset, 1, rate,
                                       "Unknown");
    } else {
      phdr->has_data_rate = TRUE;
      phdr->data_rate = rate;
      proto_tree_add_uint_format_value(wlan_tree, hf_netmon_802_11_datarate,
                                       tvb, offset, 1, rate,
                                       "%f Mb/s", rate*.5);
    }
    offset += 1;
  } else
    offset += 13;

  /*
   * ullTimestamp?
   *
   * If so, should this check the presense flag in flags?
   */
  phdr->has_tsf_timestamp = TRUE;
  phdr->tsf_timestamp = tvb_get_letoh64(tvb, offset);
  proto_tree_add_item(wlan_tree, hf_netmon_802_11_timestamp, tvb, offset, 8,
                      ENC_LITTLE_ENDIAN);
  /*offset += 8;*/

skip:
  offset = length;

  /* dissect the 802.11 packet next */
  next_tvb = tvb_new_subset_remaining(tvb, offset);
  call_dissector_with_data(ieee80211_radio_handle, next_tvb, pinfo, tree, phdr);
  return offset;
}
Пример #2
0
static void
dissect_rtacser_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Set up structures needed to add the protocol subtree and manage it */
    proto_item    *rtacser_item, *ts_item, *cl_item, *data_payload;
    proto_tree    *rtacser_tree, *cl_tree;
    int           offset = 0, len;
    guint         event_type;
    guint32       timestamp1, timestamp2;
    gboolean      cts, dcd, dsr, rts, dtr, ring, mbok;
    tvbuff_t      *payload_tvb;

    len = RTACSER_HEADER_LEN;

    /* Make entries in Protocol column on summary display */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "RTAC Serial");
    col_clear(pinfo->cinfo, COL_INFO);

    rtacser_item = proto_tree_add_protocol_format(tree, proto_rtacser, tvb, 0, len, "RTAC Serial Line");
    rtacser_tree = proto_item_add_subtree(rtacser_item, ett_rtacser);

    /* Time-stamp is stored as 2 x 32-bit unsigned integers, the left and right-hand side of the decimal point respectively */
    /* The format mirrors the timeval struct - absolute Epoch time (seconds since 1/1/1970) with an added microsecond component */
    timestamp1 = tvb_get_ntohl(tvb, offset);
    timestamp2 = tvb_get_ntohl(tvb, offset+4);
    ts_item = proto_tree_add_item(rtacser_tree, hf_rtacser_timestamp, tvb, offset, 8, ENC_BIG_ENDIAN);
    proto_item_set_text(ts_item, "Arrived At Time: %u.%u" , timestamp1, timestamp2);
    offset += 8;

    /* Set INFO column with RTAC Serial Event Type */
    event_type = tvb_get_guint8(tvb, offset);
    col_add_fstr(pinfo->cinfo, COL_INFO, "%-21s", val_to_str_const(event_type, rtacser_eventtype_vals, "Unknown Type"));

    /* Add event type to tree */
    proto_tree_add_item(rtacser_tree, hf_rtacser_event_type, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset += 1;

    /* Retrieve EIA-232 serial control line states */
    cts  = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_CTS;
    dcd  = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_DCD;
    dsr  = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_DSR;
    rts  = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_RTS;
    dtr  = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_DTR;
    ring = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_RING;
    mbok = tvb_get_guint8(tvb, offset) & RTACSER_CTRL_MBOK;

    cl_tree = proto_tree_add_subtree(rtacser_tree, tvb, offset, 1, ett_rtacser_cl, &cl_item, "Control Lines");

    /* Add UART Control Line information to INFO column */
    col_append_str(pinfo->cinfo, COL_INFO, " ( ");
    (cts)  ? col_append_str(pinfo->cinfo, COL_INFO, "CTS") : col_append_str(pinfo->cinfo, COL_INFO, "/CTS");
    (dcd)  ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DCD")  : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/DCD");
    (dsr)  ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DSR")  : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/DSR");
    (rts)  ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RTS")  : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/RTS");
    (dtr)  ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "DTR")  : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/DTR");
    (ring) ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "RING") : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/RING");
    (mbok) ? col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "MBOK") : col_append_sep_str(pinfo->cinfo, COL_INFO, NULL, "/MBOK");
    col_append_str(pinfo->cinfo, COL_INFO, " )");

    /* Add UART Control Line information to tree */
    proto_item_append_text(cl_item, " (");
    (cts)  ? proto_item_append_text(cl_item, "CTS, ") : proto_item_append_text(cl_item, "/CTS, ");
    (dcd)  ? proto_item_append_text(cl_item, "DCD, ") : proto_item_append_text(cl_item, "/DCD, ");
    (dsr)  ? proto_item_append_text(cl_item, "DSR, ") : proto_item_append_text(cl_item, "/DSR, ");
    (rts)  ? proto_item_append_text(cl_item, "RTS, ") : proto_item_append_text(cl_item, "/RTS, ");
    (dtr)  ? proto_item_append_text(cl_item, "DTR, ") : proto_item_append_text(cl_item, "/DTR, ");
    (ring) ? proto_item_append_text(cl_item, "RING, ") : proto_item_append_text(cl_item, "/RING, ");
    (mbok) ? proto_item_append_text(cl_item, "MBOK") : proto_item_append_text(cl_item, "/MBOK");
    proto_item_append_text(cl_item, ")");

    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_cts,  tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_dcd,  tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_dsr,  tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_rts,  tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_dtr,  tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_ring, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(cl_tree, hf_rtacser_ctrl_mbok, tvb, offset, 1, ENC_BIG_ENDIAN);
    offset += 1;

    /* 2-byte footer */
    proto_tree_add_item(rtacser_tree, hf_rtacser_footer, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    /* If no payload dissector has been selected, indicate to the user the preferences options */
    if ((tvb_reported_length_remaining(tvb, offset) > 0) && (global_rtacser_payload_proto == RTACSER_PAYLOAD_NONE)) {
        data_payload = proto_tree_add_item(tree, hf_rtacser_data, tvb, offset, -1, ENC_NA);
        proto_item_set_text(data_payload,"Payload Protocol not selected.  Check 'Preferences-> Protocols-> RTAC Serial' for options");
        return;
    }


    /* Determine correct message type and call appropriate dissector */
    if (tvb_reported_length_remaining(tvb, RTACSER_HEADER_LEN) > 0) {

        switch (global_rtacser_payload_proto) {
            case RTACSER_PAYLOAD_SELFM:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(selfm_handle, payload_tvb, pinfo, tree);
                break;
            case RTACSER_PAYLOAD_DNP3:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(dnp3_handle, payload_tvb, pinfo, tree);
                break;
            case RTACSER_PAYLOAD_MODBUS:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(modbus_handle, payload_tvb, pinfo, tree);
                break;
            case RTACSER_PAYLOAD_SYNPHASOR:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(synphasor_handle, payload_tvb, pinfo, tree);
                break;
            case RTACSER_PAYLOAD_LG8979:
                payload_tvb = tvb_new_subset_remaining(tvb, RTACSER_HEADER_LEN);
                call_dissector(lg8979_handle, payload_tvb, pinfo, tree);
                break;
            default:
                break;
        }
    }

}
Пример #3
0
static int
dissect_json(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
	proto_tree *json_tree = NULL;
	proto_item *ti = NULL;

	json_parser_data_t parser_data;
	tvbparse_t *tt;

	http_message_info_t *message_info;
	const char *data_name;
	int offset;

	/* JSON dissector can be called in a JSON native file or when transported
	 * by another protocol. We set the column values only if they've not been
	 * already set by someone else.
	 */
	wmem_list_frame_t *proto = wmem_list_frame_prev(wmem_list_tail(pinfo->layers));
	if (proto) {
		const char *name = proto_get_protocol_filter_name(GPOINTER_TO_INT(wmem_list_frame_data(proto)));

		if (!strcmp(name, "frame")) {
			col_set_str(pinfo->cinfo, COL_PROTOCOL, "JSON");
			col_set_str(pinfo->cinfo, COL_INFO, "JavaScript Object Notation");
		}
	}

	data_name = pinfo->match_string;
	if (! (data_name && data_name[0])) {
		/*
		 * No information from "match_string"
		 */
		message_info = (http_message_info_t *)data;
		if (message_info == NULL) {
			/*
			 * No information from dissector data
			 */
			data_name = NULL;
		} else {
			data_name = message_info->media_str;
			if (! (data_name && data_name[0])) {
				/*
				 * No information from dissector data
				 */
				data_name = NULL;
			}
		}
	}

	if (tree) {
		ti = proto_tree_add_item(tree, hfi_json, tvb, 0, -1, ENC_NA);
		json_tree = proto_item_add_subtree(ti, ett_json);

		if (data_name)
			proto_item_append_text(ti, ": %s", data_name);
	}

	offset = 0;

	parser_data.stack = wmem_stack_new(wmem_packet_scope());
	wmem_stack_push(parser_data.stack, json_tree);

	if (json_compact) {
		proto_tree *json_tree_compact = NULL;
		json_tree_compact = proto_tree_add_subtree(json_tree, tvb, 0, -1, ett_json_compact, NULL, "JSON compact form:");

		parser_data.stack_compact = wmem_stack_new(wmem_packet_scope());
		wmem_stack_push(parser_data.stack_compact, json_tree_compact);

		parser_data.array_idx = wmem_stack_new(wmem_packet_scope());
		wmem_stack_push(parser_data.array_idx, GINT_TO_POINTER(JSON_COMPACT_TOP_ITEM)); /* top element */
	}


	tt = tvbparse_init(tvb, offset, -1, &parser_data, want_ignore);

	/* XXX, only one json in packet? */
	while ((tvbparse_get(tt, want)))
		;

	offset = tvbparse_curr_offset(tt);

	proto_item_set_len(ti, offset);

	/* if we have some unparsed data, pass to data-text-lines dissector (?) */
	if (tvb_reported_length_remaining(tvb, offset) > 0) {
		tvbuff_t *next_tvb;

		next_tvb = tvb_new_subset_remaining(tvb, offset);

		call_dissector_with_data(text_lines_handle, next_tvb, pinfo, tree, data);
	} else if (data_name) {
		col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)", data_name);
	}

	return tvb_captured_length(tvb);
}
Пример #4
0
static int dissect_packetlogger(tvbuff_t *tvb, packet_info *pinfo,
        proto_tree *tree, void *data)
{
  proto_tree        *packetlogger_tree = NULL;
  tvbuff_t          *next_tvb;
  proto_item        *ti = NULL;
  guint8             pl_type;
  gint               len;
  bluetooth_data_t  *bluetooth_data;
  struct bthci_phdr  bthci;

  bluetooth_data = (bluetooth_data_t *) data;

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

  ti = proto_tree_add_item (tree, proto_packetlogger, tvb, 0, -1, ENC_NA);
  packetlogger_tree = proto_item_add_subtree (ti, ett_packetlogger);

  pl_type = tvb_get_guint8 (tvb, 0);
  proto_tree_add_item (packetlogger_tree, hf_type, tvb, 0, 1, ENC_BIG_ENDIAN);
  proto_item_append_text (ti, " %s", val_to_str (pl_type, type_vals, "Unknown 0x%02x"));

  len = tvb_reported_length_remaining (tvb, 1);
  next_tvb = tvb_new_subset_remaining (tvb, 1);

  if (pl_type <= PKT_RECV_ACL_DATA) {
    /* HCI H1 packages */
    switch (pl_type) {
    case PKT_HCI_COMMAND:
      bthci.channel = BTHCI_CHANNEL_COMMAND;
      bthci.sent = P2P_DIR_SENT;
      pinfo->p2p_dir = P2P_DIR_SENT;
      break;
    case PKT_HCI_EVENT:
      bthci.channel = BTHCI_CHANNEL_EVENT;
      bthci.sent = P2P_DIR_RECV;
      pinfo->p2p_dir = P2P_DIR_RECV;
      break;
    case PKT_SENT_ACL_DATA:
      bthci.channel = BTHCI_CHANNEL_ACL;
      bthci.sent = P2P_DIR_SENT;
      pinfo->p2p_dir = P2P_DIR_SENT;
      break;
    case PKT_RECV_ACL_DATA:
      bthci.channel = BTHCI_CHANNEL_ACL;
      bthci.sent = P2P_DIR_RECV;
      pinfo->p2p_dir = P2P_DIR_RECV;
      break;
    default:
      bthci.channel = pl_type;
      bthci.sent = P2P_DIR_UNKNOWN;
      pinfo->p2p_dir = P2P_DIR_UNKNOWN;
      break;
    }
    bluetooth_data->previous_protocol_data.bthci = &bthci;
    proto_item_set_len (ti, 1);

    col_add_fstr (pinfo->cinfo, COL_INFO, "%s", val_to_str(pl_type, type_vals, "Unknown 0x%02x"));
    if (!dissector_try_uint_new(hci_h1_table, bthci.channel,
            next_tvb, pinfo, tree, TRUE, bluetooth_data)) {
      call_dissector (data_handle, next_tvb, pinfo, tree);
    }
  } else {
    /* PacketLogger data */
    switch (pl_type) {
    case PKT_POWER:
    case PKT_NOTE:
    case PKT_NEW_CONTROLLER:
      proto_tree_add_item (packetlogger_tree, hf_info, next_tvb, 0, len, ENC_ASCII|ENC_NA);
      col_add_fstr (pinfo->cinfo, COL_INFO, "%s", tvb_format_stringzpad_wsp (next_tvb, 0, len));
      break;
    default:
      call_dissector (data_handle, next_tvb, pinfo, tree);
      col_add_fstr (pinfo->cinfo, COL_INFO, "Unknown 0x%02x", pl_type);
      break;
    }
  }

  return tvb_captured_length(tvb);
}
static void
dissect_wlancap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree *wlan_tree = NULL;
    proto_item *ti;
    tvbuff_t *next_tvb;
    int offset;
    guint32 version;
    guint32 length;
    guint32 channel;
    guint32 datarate;
    guint32 ssi_type;
    guint32 antnoise;

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

    version = tvb_get_ntohl(tvb, offset) - WLANCAP_MAGIC_COOKIE_BASE;

    length = tvb_get_ntohl(tvb, offset+4);

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

    if (version > 2) {
        goto skip;
    }

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

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

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

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

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

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

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

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

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

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

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


skip:
    offset = length;

    /* dissect the 802.11 header next */
    next_tvb = tvb_new_subset_remaining(tvb, offset);
    call_dissector(ieee80211_handle, next_tvb, pinfo, tree);
}
Пример #6
0
void
dissect_802_3(volatile int length, gboolean is_802_2, tvbuff_t *tvb,
              int offset_after_length, packet_info *pinfo, proto_tree *tree,
              proto_tree *fh_tree, int length_id, int trailer_id, expert_field* ei_len,
              int fcs_len)
{
  proto_item *length_it;
  tvbuff_t   *volatile next_tvb = NULL;
  tvbuff_t   *trailer_tvb = NULL;
  const char *saved_proto;
  gint        captured_length, reported_length;

  length_it = proto_tree_add_uint(fh_tree, length_id, tvb,
                                  offset_after_length - 2, 2, length);

  /* Get the length of the payload.
     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.) */
  reported_length = tvb_reported_length_remaining(tvb, offset_after_length);
  if (fcs_len > 0) {
    if (reported_length >= fcs_len)
      reported_length -= fcs_len;
  }

  /* Make sure the length in the 802.3 header doesn't go past the end of
     the payload. */
  if (length > reported_length) {
    length = reported_length;
    expert_add_info(pinfo, length_it, ei_len);
  }

  /* Give the next dissector only 'length' number of bytes. */
  captured_length = tvb_captured_length_remaining(tvb, offset_after_length);
  if (captured_length > length)
    captured_length = length;
  next_tvb = tvb_new_subset(tvb, offset_after_length, captured_length, length);

  /* Dissect the payload either as IPX or as an LLC frame.
     Catch non-fatal 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;
  TRY {
    if (is_802_2)
      call_dissector(llc_handle, next_tvb, pinfo, tree);
    else {
      /* Check if first three bits of payload are 0x7.
         If so, then payload is IPX.  If not, then it's CCSDS.
         Refer to packet-eth.c for setting of is_802_2 variable. */
      if (tvb_get_bits8(next_tvb, 0, 3) == 7)
        call_dissector(ipx_handle, next_tvb, pinfo, tree);
      else
        call_dissector(ccsds_handle, next_tvb, pinfo, tree);
    }
  }
  CATCH_NONFATAL_ERRORS {
    /* Somebody threw an exception that means that there was a problem
       dissecting the payload; that means that a dissector was found,
       so we don't need to dissect the payload as data or update the
       protocol or info columns.

       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);
  }
  ENDTRY;

  /* Restore the protocol value, so that any exception thrown by
     tvb_new_subset_remaining() refers to the protocol for which
     this is a trailer. */
  pinfo->current_proto = saved_proto;

  /* Construct a tvbuff for the trailer; if the trailer is past the
     end of the captured data, this will throw a BoundsError, which
     is what we want, as it'll report that the packet was cut short. */
  trailer_tvb = tvb_new_subset_remaining(tvb, offset_after_length + length);

  add_ethernet_trailer(pinfo, tree, fh_tree, trailer_id, tvb, trailer_tvb, fcs_len);
}
Пример #7
0
static void
dissect_interlink(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	int		offset = 0;
	proto_tree	*il_tree = NULL;
	proto_tree	*ilh_tree = NULL;
	proto_tree	*ilb_tree = NULL;
	guint8		ilb_type;
	guint8		ilb_version;
	guint16		type_version = 0;
	dissector_handle_t	handle;
	tvbuff_t	*next_tvb;

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

	if (tree) {
		proto_item	*il_item;
		il_item = proto_tree_add_item(tree, proto_interlink,
								tvb, 0, 16, FALSE);
		if (il_item)
			il_tree = proto_item_add_subtree(il_item, ett_interlink);
	}

	if (il_tree) {
		proto_item	*ilh_item = NULL;
		ilh_item = proto_tree_add_text(il_tree, tvb, 0, 12, "Interlink Header");
		if (ilh_item)
			ilh_tree = proto_item_add_subtree(ilh_item, ett_interlink_header);
	}

	if (ilh_tree) {
		proto_tree_add_item(ilh_tree, hf_interlink_id, tvb, offset, 4, FALSE);
		offset += 4;
		proto_tree_add_item(ilh_tree, hf_interlink_version, tvb, offset, 2, TRUE);
		offset += 2;
		proto_tree_add_item(ilh_tree, hf_interlink_cmd, tvb, offset, 2, TRUE);
		offset += 2;
		proto_tree_add_item(ilh_tree, hf_interlink_seq, tvb, offset, 2, TRUE);
		offset += 2;
	}

	if (ilh_tree) {
		proto_item	*flags_item;
		proto_tree	*flags_tree = NULL;

		flags_item = proto_tree_add_item(ilh_tree, hf_interlink_flags,
			tvb, offset, 2, TRUE);
		if (flags_item) {
			flags_tree = proto_item_add_subtree(flags_item, ett_interlink_flags);
		}
		if (flags_tree) {
			guint16		il_flags;
			il_flags = tvb_get_letohs(tvb, offset);
			proto_tree_add_boolean(flags_tree, hf_interlink_flags_req_ack, tvb, offset, 2, il_flags);
			proto_tree_add_boolean(flags_tree, hf_interlink_flags_inc_ack_port, tvb, offset, 2, il_flags);
		}
	}
	offset += 2;

	if (tree) {
		proto_item	*ilb_item;
		ilb_item = proto_tree_add_text(il_tree, tvb, offset, 4, "Block Header");
		if (ilb_item)
			ilb_tree = proto_item_add_subtree(ilb_item, ett_interlink_block);
	}

	ilb_type = tvb_get_guint8(tvb, offset);
	ilb_version = tvb_get_guint8(tvb, offset + 1);
	type_version = ilb_type << 8 | ilb_version;
	col_append_fstr(pinfo->cinfo, COL_INFO, "Type: 0x%02x, Version: %d",
		ilb_type, ilb_version);

	if (ilb_tree) {
		proto_tree_add_item(ilb_tree, hf_interlink_block_type, tvb, offset, 1, FALSE);
		offset += 1;
		proto_tree_add_item(ilb_tree, hf_interlink_block_version, tvb, offset, 1, FALSE);
		offset += 1;
		proto_tree_add_item(ilb_tree, hf_interlink_block_length, tvb, offset, 2, TRUE);
		offset += 2;
	}

	/* Generate a new tvb for the rest. */
	next_tvb = tvb_new_subset_remaining(tvb, offset);

	/* Probably a sub-dissector exists for this type/version combination. */
	handle = dissector_get_port_handle(subdissector_table, type_version);

	/* Without a proper sub-dissector, we use "data". */
	if (handle == NULL) handle = data_handle;

	/* Call the sub-dissector. */
	call_dissector(handle, next_tvb, pinfo, tree);
}
/* 
 * Main dissection routine which dissects a DDP segment and interprets the
 * header field rsvdULP according to RDMAP.
 */
void
dissect_iwarp_ddp_rdmap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree *ddp_rdma_tree = NULL;
	proto_tree *ddp_tree = NULL;
	proto_tree *ddp_ctrl_field_tree = NULL;
	proto_tree *ddp_buffer_model_tree = NULL;
	proto_tree *rdma_tree = NULL;
	proto_tree *rdma_ctrl_field_tree = NULL;

	proto_item *ddp_rdma_item = NULL;
	proto_item *ddp_item = NULL;
	proto_item *ddp_ctrl_field_item = NULL;
	proto_item *ddp_buffer_model_item = NULL;
	proto_item *rdma_item = NULL;
	proto_item *rdma_ctrl_field_item = NULL;

	tvbuff_t *next_tvb = NULL;
	
	gboolean is_tagged_buffer_model;
	guint8 ddp_ctrl_field, rdma_ctrl_field, rdma_msg_opcode;
	guint32 header_end;
	guint32 offset = 0;

	ddp_ctrl_field = tvb_get_guint8(tvb, 0);
	rdma_ctrl_field = tvb_get_guint8(tvb, 1);
	rdma_msg_opcode = rdma_ctrl_field & RDMA_OPCODE;
	is_tagged_buffer_model = ddp_ctrl_field & DDP_TAGGED_FLAG;

	ddp_rdma_packetlist(pinfo, ddp_ctrl_field & DDP_LAST_FLAG, rdma_msg_opcode);
	
	if (tree) {
		
		offset = 0;
		
		/* determine header length */
		if (is_tagged_buffer_model) {
			header_end = DDP_TAGGED_HEADER_LEN;
		} else {
			header_end = DDP_UNTAGGED_HEADER_LEN;
		}
		
		if (rdma_msg_opcode == RDMA_READ_REQUEST
				|| rdma_msg_opcode == RDMA_TERMINATE) {
			header_end = -1;
		}
		
		/* DDP/RDMA protocol tree */
		ddp_rdma_item = proto_tree_add_item(tree, proto_iwarp_ddp_rdmap,
				tvb, offset, header_end, FALSE);
		ddp_rdma_tree = proto_item_add_subtree(ddp_rdma_item,
				ett_iwarp_ddp_rdmap);

		/* DDP protocol header subtree */	
		ddp_item = proto_tree_add_item(ddp_rdma_tree, hf_iwarp_ddp, tvb,
				offset, header_end, FALSE);
		ddp_tree = proto_item_add_subtree(ddp_item, ett_iwarp_ddp);

		/* DDP control field */
		ddp_ctrl_field_item = proto_tree_add_item(ddp_tree,
				hf_iwarp_ddp_control_field, tvb, offset,
				DDP_CONTROL_FIELD_LEN, FALSE);
		ddp_ctrl_field_tree = proto_item_add_subtree(ddp_ctrl_field_item,
				ett_iwarp_ddp);
		
		proto_tree_add_item(ddp_ctrl_field_tree, hf_iwarp_ddp_t_flag, tvb,
				offset, DDP_CONTROL_FIELD_LEN, FALSE);
		proto_tree_add_item(ddp_ctrl_field_tree, hf_iwarp_ddp_l_flag, tvb,
				offset, DDP_CONTROL_FIELD_LEN, FALSE);
		proto_tree_add_item(ddp_ctrl_field_tree, hf_iwarp_ddp_rsvd, tvb,
				offset, DDP_CONTROL_FIELD_LEN, FALSE);
		proto_tree_add_item(ddp_ctrl_field_tree, hf_iwarp_ddp_dv, tvb, offset,
				DDP_CONTROL_FIELD_LEN, FALSE);
		offset += DDP_CONTROL_FIELD_LEN;
		
		
		/* DDP header field RsvdULP */
		if (!is_tagged_buffer_model) {
			proto_tree_add_item(ddp_tree, hf_iwarp_ddp_rsvdulp, tvb,
					offset, DDP_UNTAGGED_RSVDULP_LEN, FALSE);
		}
		
		/* RDMA protocol header subtree */
		if (is_tagged_buffer_model) {
			header_end = RDMA_CONTROL_FIELD_LEN;
		} else {
			header_end = RDMA_CONTROL_FIELD_LEN + RDMA_RESERVED_FIELD_LEN;
		}
		
		rdma_item = proto_tree_add_item(ddp_rdma_tree, hf_iwarp_rdma, tvb,
					offset, header_end, FALSE);
		rdma_tree = proto_item_add_subtree(rdma_item, ett_iwarp_rdma);

		/* RDMA Control Field */
		rdma_ctrl_field_item = proto_tree_add_item(rdma_tree,
				hf_iwarp_rdma_control_field, tvb, offset,
				RDMA_CONTROL_FIELD_LEN, FALSE);
		rdma_ctrl_field_tree = proto_item_add_subtree(rdma_ctrl_field_item,
				ett_iwarp_rdma);
		
		proto_tree_add_item(rdma_ctrl_field_tree, hf_iwarp_rdma_version, tvb,
				offset, RDMA_CONTROL_FIELD_LEN, FALSE);
		proto_tree_add_item(rdma_ctrl_field_tree, hf_iwarp_rdma_rsvd, tvb,
				offset, RDMA_CONTROL_FIELD_LEN, FALSE);
		proto_tree_add_item(rdma_ctrl_field_tree, hf_iwarp_rdma_opcode, tvb,
				offset, RDMA_CONTROL_FIELD_LEN, FALSE);
		offset += RDMA_CONTROL_FIELD_LEN;
		
		/* dissection of DDP rsvdULP[8:39] with respect to RDMAP */
		if (rdma_msg_opcode == RDMA_READ_REQUEST
				|| rdma_msg_opcode == RDMA_SEND
				|| rdma_msg_opcode == RDMA_SEND_SE
				|| rdma_msg_opcode == RDMA_TERMINATE) {
			proto_tree_add_item(rdma_tree, hf_iwarp_rdma_reserved,
				 tvb, offset, RDMA_RESERVED_FIELD_LEN, FALSE);
		}
		
		if (rdma_msg_opcode == RDMA_SEND_INVALIDATE
				|| rdma_msg_opcode == RDMA_SEND_SE_INVALIDATE) {
			proto_tree_add_item(rdma_tree, hf_iwarp_rdma_inval_stag,
				tvb, offset, RDMA_INVAL_STAG_LEN, FALSE);
		}
		
		if (!is_tagged_buffer_model) {
			offset += RDMA_RESERVED_FIELD_LEN;
		}

		/* DDP Buffer Model dissection */
		if (is_tagged_buffer_model) {

			/* Tagged Buffer Model Case */
			ddp_buffer_model_item = proto_tree_add_item(ddp_tree,
					hf_iwarp_ddp_tagged_header, tvb, offset,
					DDP_BUFFER_MODEL_LEN, FALSE);
			ddp_buffer_model_tree = proto_item_add_subtree(ddp_buffer_model_item,
					ett_iwarp_ddp);

			proto_tree_add_item(ddp_buffer_model_tree, hf_iwarp_ddp_stag, tvb,
					offset, DDP_STAG_LEN, FALSE);
			offset += DDP_STAG_LEN;
			proto_tree_add_item(ddp_buffer_model_tree, hf_iwarp_ddp_to, tvb,
					offset, DDP_TO_LEN, FALSE);
			offset += DDP_TO_LEN;
			
			if( rdma_msg_opcode == RDMA_READ_RESPONSE
					|| rdma_msg_opcode == RDMA_WRITE) {
				
				/* display the payload */
				next_tvb = tvb_new_subset_remaining(tvb, DDP_TAGGED_HEADER_LEN);
				call_dissector(data_handle, next_tvb, pinfo, tree);
			}
			
		} else {
			
			/* Untagged Buffer Model Case */
			ddp_buffer_model_item = proto_tree_add_item(ddp_tree,
					hf_iwarp_ddp_untagged_header, tvb, offset,
					DDP_BUFFER_MODEL_LEN, FALSE);
			ddp_buffer_model_tree = proto_item_add_subtree(ddp_buffer_model_item,
					ett_iwarp_ddp);

			proto_tree_add_item(ddp_buffer_model_tree, hf_iwarp_ddp_qn, tvb,
					offset, DDP_QN_LEN, FALSE);
			offset += DDP_QN_LEN;
			proto_tree_add_item(ddp_buffer_model_tree, hf_iwarp_ddp_msn, tvb,
					offset, DDP_MSN_LEN, FALSE);
			offset += DDP_MSN_LEN;
			proto_tree_add_item(ddp_buffer_model_tree, hf_iwarp_ddp_mo, tvb,
					offset, DDP_MO_LEN, FALSE);
			offset += DDP_MO_LEN;
			
			if (rdma_msg_opcode == RDMA_SEND
					|| rdma_msg_opcode == RDMA_SEND_INVALIDATE
					|| rdma_msg_opcode == RDMA_SEND_SE
					|| rdma_msg_opcode == RDMA_SEND_SE_INVALIDATE) {

				/* display the payload */
				next_tvb = tvb_new_subset_remaining(tvb, DDP_UNTAGGED_HEADER_LEN);
				call_dissector(data_handle, next_tvb, pinfo, tree);
			}
		}
	}

	/* do further dissection for RDMA messages RDMA Read Request & Terminate */
	if (rdma_msg_opcode == RDMA_READ_REQUEST
			|| rdma_msg_opcode == RDMA_TERMINATE) {
		dissect_iwarp_rdmap(tvb, rdma_tree, offset, rdma_msg_opcode);
	}
}
Пример #9
0
static void
dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_tree     *clnp_tree = NULL;
  proto_item     *ti, *ti_len = NULL, *ti_pdu_len = NULL, *ti_tot_len = NULL;
  guint8          cnf_proto_id;
  guint8          cnf_hdr_len;
  guint8          cnf_vers;
  guint8          cnf_ttl;
  guint8          cnf_type;
  char            flag_string[6+1];
  const char     *pdu_type_string;
  proto_tree     *type_tree;
  guint16         segment_length;
  guint16         du_id = 0;
  guint16         segment_offset = 0;
  guint16         total_length;
  guint16         cnf_cksum;
  cksum_status_t  cksum_status;
  int             offset;
  guchar          src_len, dst_len, nsel, opt_len = 0;
  const guint8   *dst_addr, *src_addr;
  guint           next_length;
  proto_tree     *discpdu_tree;
  gboolean        save_in_error_pkt;
  fragment_data  *fd_head;
  tvbuff_t       *next_tvb;
  gboolean        update_col_info = TRUE;
  gboolean        save_fragmented;

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

  cnf_proto_id = tvb_get_guint8(tvb, P_CLNP_PROTO_ID);
  if (cnf_proto_id == NLPID_NULL) {
    col_set_str(pinfo->cinfo, COL_INFO, "Inactive subset");
    if (tree) {
      ti = proto_tree_add_item(tree, proto_clnp, tvb, P_CLNP_PROTO_ID, 1, ENC_NA);
      clnp_tree = proto_item_add_subtree(ti, ett_clnp);
      proto_tree_add_uint_format(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
                                 cnf_proto_id,
                                 "Inactive subset");
    }
    next_tvb = tvb_new_subset_remaining(tvb, 1);
    if (call_dissector(ositp_inactive_handle, next_tvb, pinfo, tree) == 0)
      call_dissector(data_handle,tvb, pinfo, tree);
    return;
  }

  /* return if version not known */
  cnf_vers = tvb_get_guint8(tvb, P_CLNP_VERS);
  if (cnf_vers != ISO8473_V1) {
    call_dissector(data_handle,tvb, pinfo, tree);
    return;
  }

  /* fixed part decoding */
  cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
	
  if (tree) {
    ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA);
    clnp_tree = proto_item_add_subtree(ti, ett_clnp);
    proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
                        cnf_proto_id);
    ti_len = proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
                                 cnf_hdr_len);
  }
  if (cnf_hdr_len < FIXED_PART_LEN) {
    /* Header length is less than the length of the fixed part of
       the header. */
    expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR,
                           "Header length value < minimum length %u",
                           FIXED_PART_LEN);
    return;
  }
  if (tree) {                   
    proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
                        cnf_vers);
    cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
    proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
                               cnf_ttl,
                               "Holding Time : %u (%u.%u secs)",
                               cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
  }

  cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
  pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
                               "Unknown (0x%02x)");
  flag_string[0] = '\0';
  if (cnf_type & CNF_SEG_OK)
    g_strlcat(flag_string, "S ", 7);
  if (cnf_type & CNF_MORE_SEGS)
    g_strlcat(flag_string, "M ", 7);
  if (cnf_type & CNF_ERR_OK)
    g_strlcat(flag_string, "E ", 7);
  if (tree) {
    ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
                                    cnf_type,
                                    "PDU Type     : 0x%02x (%s%s)",
                                    cnf_type,
                                    flag_string,
                                    pdu_type_string);
    type_tree = proto_item_add_subtree(ti, ett_clnp_type);
    proto_tree_add_item(type_tree, hf_clnp_cnf_segmentation, tvb, P_CLNP_TYPE, 1, ENC_NA);
    proto_tree_add_item(type_tree, hf_clnp_cnf_more_segments, tvb, P_CLNP_TYPE, 1, ENC_NA);
    proto_tree_add_item(type_tree, hf_clnp_cnf_report_error, tvb, P_CLNP_TYPE, 1, ENC_NA);
    proto_tree_add_item(type_tree, hf_clnp_cnf_type, tvb, P_CLNP_TYPE, 1, ENC_NA);
  }

  /* If we don't have the full header - i.e., not enough to see the
     segmentation part and determine whether this datagram is segmented
     or not - set the Info column now; we'll get an exception before
     we set it otherwise. */

  if (tvb_length(tvb) < cnf_hdr_len) {
    col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
  }

  segment_length = tvb_get_ntohs(tvb, P_CLNP_SEGLEN);
  if (tree) {
    ti_pdu_len = proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
                                     segment_length);
  }
  if (segment_length < cnf_hdr_len) {
    /* Segment length is less than the header length. */
    expert_add_info_format(pinfo, ti_pdu_len, PI_MALFORMED, PI_ERROR,
                           "PDU length < header length %u", cnf_hdr_len);
    return;
  }
  cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
  cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum);
  if (tree) {
    switch (cksum_status) {

    default:
      /*
       * No checksum present, or not enough of the header present to
       * checksum it.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x",
                                 cnf_cksum);
      break;

    case CKSUM_OK:
      /*
       * Checksum is correct.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x (correct)",
                                 cnf_cksum);
      break;

    case CKSUM_NOT_OK:
      /*
       * Checksum is not correct.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x (incorrect)",
                                 cnf_cksum);
      break;
    }
  } /* tree */

  opt_len = cnf_hdr_len;
  opt_len -= FIXED_PART_LEN; /* Fixed part of Header */

  /* address part */

  offset = P_CLNP_ADDRESS_PART;
  if (opt_len < 1) {
    /* Header length is less than the minimum value in CLNP,
       including the destination address length. */
    expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR,
                           "Header length value < %u",
                           FIXED_PART_LEN + 1);
    return;
  }
  dst_len  = tvb_get_guint8(tvb, offset);
  if (tree) {
    proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
                        dst_len);
  }
  offset += 1;
  opt_len -= 1;

  if (opt_len < dst_len) {
    /* Header length is less than the minimum value,
       including the destination address length and the
       destination address. */
    expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR,
                           "Header length value < %u",
                           FIXED_PART_LEN + 1 + dst_len);
    return;
  }
  dst_addr = tvb_get_ptr(tvb, offset, dst_len);
  nsel     = tvb_get_guint8(tvb, offset + dst_len - 1);
  SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr);
  SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr);
  if (tree) {
    proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset, dst_len,
                                dst_addr,
                                " DA : %s",
                                print_nsap_net(dst_addr, dst_len));
  }
  offset += dst_len;
  opt_len -= dst_len;

  if (opt_len < 1) {
    /* Header length is less than the minimum value,
       including the destination address length, the
       destination address, and the source address length. */
    expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR,
                           "Header length value < %u",
                           FIXED_PART_LEN + 1 + dst_len + 1);
    return;
  }
  src_len  = tvb_get_guint8(tvb, offset);
  if (tree) {
    proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
                        offset, 1, src_len);
  }
  offset += 1;
  opt_len -= 1;

  if (opt_len < src_len) {
    /* Header length is less than the minimum value,
       including the destination address length, the
       destination address, the source address length,
       and the source address. */
    expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR,
                           "Header length value < %u",
                           FIXED_PART_LEN + 1 + dst_len + 1 + src_len);
    return;
  }
  src_addr = tvb_get_ptr(tvb, offset, src_len);
  SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr);
  SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr);
  if (tree) {
    proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb,
                                offset, src_len,
                                src_addr,
                                " SA : %s",
                                print_nsap_net(src_addr, src_len));

  }
  offset += src_len;
  opt_len -= src_len;

  /* Segmentation Part */

  if (cnf_type & CNF_SEG_OK) {
    if (opt_len < SEGMENTATION_PART_LEN) {
      /* Header length is less than the minimum value,
         including the destination address length, the
         destination address, the source address length,
         the source address, and the segmentation part. */
      expert_add_info_format(pinfo, ti_len, PI_MALFORMED, PI_ERROR,
                             "Header length value < %u",
                             FIXED_PART_LEN + 1 + dst_len + 1 + SEGMENTATION_PART_LEN);
      return;
    }
    du_id = tvb_get_ntohs(tvb, offset);
    if (tree) {
      proto_tree_add_text(clnp_tree, tvb, offset, 2,
                          "Data unit identifier: %06u",
                          du_id);
    }
    segment_offset = tvb_get_ntohs(tvb, offset + 2);
    if (tree) {
      proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
                          "Segment offset      : %6u",
                          segment_offset);
    }
    total_length = tvb_get_ntohs(tvb, offset + 4);
    if (tree) {
      ti_tot_len = proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
                                       "Total length        : %6u",
                                       total_length);
    }
    if (total_length < segment_length) {
      /* Reassembled length is less than the length of this segment. */
      expert_add_info_format(pinfo, ti_tot_len, PI_MALFORMED, PI_ERROR,
                             "Total length < segment length %u", segment_length);
      return;
    }
    offset  += SEGMENTATION_PART_LEN;
    opt_len -= SEGMENTATION_PART_LEN;
  }

  if (tree) {
    dissect_osi_options(opt_len, tvb, offset, clnp_tree);
  }

  offset += opt_len;

  /* If clnp_reassemble is on, this is a segment, we have all the
   * data in the segment, and the checksum is valid, then just add the
   * segment to the hashtable.
   */
  save_fragmented = pinfo->fragmented;
  if (clnp_reassemble && (cnf_type & CNF_SEG_OK) &&
      ((cnf_type & CNF_MORE_SEGS) || segment_offset != 0) &&
      tvb_bytes_exist(tvb, offset, segment_length - cnf_hdr_len) &&
      segment_length > cnf_hdr_len &&
      cksum_status != CKSUM_NOT_OK) {
    fd_head = fragment_add_check(&clnp_reassembly_table,
                                 tvb, offset, pinfo, du_id, NULL,
                                 segment_offset, segment_length - cnf_hdr_len,
                                 cnf_type & CNF_MORE_SEGS);

    next_tvb = process_reassembled_data(tvb, offset, pinfo, "Reassembled CLNP",
                                        fd_head, &clnp_frag_items, &update_col_info, clnp_tree);
  } else {
    /* If this is the first segment, dissect its contents, otherwise
       just show it as a segment.

       XXX - if we eventually don't save the reassembled contents of all
       segmented datagrams, we may want to always reassemble. */
    if ((cnf_type & CNF_SEG_OK) && segment_offset != 0) {
      /* Not the first segment - don't dissect it. */
      next_tvb = NULL;
    } else {
      /* First segment, or not segmented.  Dissect what we have here. */

      /* Get a tvbuff for the payload.  Set its length to the segment
         length, and flag it as a fragment, so going past the end
         reports FragmentBoundsError, i.e. "there's data missing
         because this isn't reassembled", not ReportedBoundsError,
         i.e. "the dissector ran past the end of the packet, so the
         packet must not have been constructed properly". */
      next_tvb = tvb_new_subset_length(tvb, offset, segment_length - cnf_hdr_len);
      tvb_set_fragment(next_tvb);

      /*
       * If this is the first segment, but not the only segment,
       * tell the next protocol that.
       */
      if ((cnf_type & (CNF_SEG_OK|CNF_MORE_SEGS)) == (CNF_SEG_OK|CNF_MORE_SEGS))
        pinfo->fragmented = TRUE;
      else
        pinfo->fragmented = FALSE;
    }
  }

  if (next_tvb == NULL) {
    /* Just show this as a segment. */
    col_add_fstr(pinfo->cinfo, COL_INFO, "Fragmented %s NPDU %s(off=%u)",
                 pdu_type_string, flag_string, segment_offset);

    /* As we haven't reassembled anything, we haven't changed "pi", so
       we don't have to restore it. */
    call_dissector(data_handle, tvb_new_subset_remaining(tvb, offset), pinfo,
                   tree);
    pinfo->fragmented = save_fragmented;
    return;
  }

  if (tvb_offset_exists(tvb, offset)) {
    switch (cnf_type & CNF_TYPE) {

    case DT_NPDU:
    case MD_NPDU:
      /* Continue with COTP if any data.
         XXX - if this isn't the first Derived PDU of a segmented Initial
         PDU, skip that? */

      if (nsel == (guchar)tp_nsap_selector || always_decode_transport) {
        if (call_dissector(ositp_handle, next_tvb, pinfo, tree) != 0) {
          pinfo->fragmented = save_fragmented;
          return;       /* yes, it appears to be COTP or CLTP */
        }
      }
      if (dissector_try_heuristic(clnp_heur_subdissector_list, next_tvb,
                                  pinfo, tree, NULL)) {
          pinfo->fragmented = save_fragmented;
          return;       /* yes, it appears to be one of the protocols in the heuristic list */
      }

      break;

    case ER_NPDU:
      /* The payload is the header and "none, some, or all of the data
         part of the discarded PDU", i.e. it's like an ICMP error;
         dissect it as a CLNP PDU. */

      col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
      next_length = tvb_length_remaining(tvb, offset);
      if (next_length != 0) {
          /* We have payload; dissect it. */
          ti = proto_tree_add_text(clnp_tree, tvb, offset, next_length,
            "Discarded PDU");
          discpdu_tree = proto_item_add_subtree(ti, ett_clnp_disc_pdu);

          /* Save the current value of the "we're inside an error packet"
             flag, and set that flag; subdissectors may treat packets
             that are the payload of error packets differently from
             "real" packets. */
          save_in_error_pkt = pinfo->flags.in_error_pkt;
          pinfo->flags.in_error_pkt = TRUE;

          call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);

          /* Restore the "we're inside an error packet" flag. */
          pinfo->flags.in_error_pkt = save_in_error_pkt;
      }
      pinfo->fragmented = save_fragmented;
      return;   /* we're done with this PDU */

    case ERQ_NPDU:
    case ERP_NPDU:
      /* XXX - dissect this */
      break;
    }
  }
  col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
  call_dissector(data_handle,next_tvb, pinfo, tree);
  pinfo->fragmented = save_fragmented;
} /* dissect_clnp */
Пример #10
0
/* Code to actually dissect the packets */
static void
dissect_mip( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  /* Set up structures we will need to add the protocol subtree and manage it */
  proto_item	*ti;
  proto_tree	*mip_tree=NULL;
  proto_item    *tf;
  proto_tree    *flags_tree;
  guint8         type;
  guint16        flags;
  gint           offset=0;
  const guint8  *reftime;
  tvbuff_t      *next_tvb;

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

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

  type = tvb_get_guint8(tvb, offset);
  switch (type) {
  case MIP_REGISTRATION_REQUEST:
	col_add_fstr(pinfo->cinfo, COL_INFO,
		       "Reg Request: HoA=%s HA=%s CoA=%s",
		       ip_to_str(tvb_get_ptr(tvb,4,4)),
		       ip_to_str(tvb_get_ptr(tvb,8,4)),
		       ip_to_str(tvb_get_ptr(tvb,12,4)));

	if (tree) {
	  ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
	  mip_tree = proto_item_add_subtree(ti, ett_mip);

	  /* type */
	  proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
	  offset++;

	  /* flags */
	  flags = tvb_get_guint8(tvb, offset);
	  tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 1, flags);
	  flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_s, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_b, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_d, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_m, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_g, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_v, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_t, tvb, offset, 1, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_x, tvb, offset, 1, flags);
	  offset++;

	  /* lifetime */
	  proto_tree_add_item(mip_tree, hf_mip_life, tvb, offset, 2, FALSE);
	  offset += 2;

	  /* home address */
	  proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* home agent address */
	  proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* Care of Address */
	  proto_tree_add_item(mip_tree, hf_mip_coa, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* Identifier - assumed to be an NTP time here */
	  reftime = tvb_get_ptr(tvb, offset, 8);
	  proto_tree_add_bytes_format(mip_tree, hf_mip_ident, tvb, offset, 8,
				      reftime,
				      "Identification: %s",
				      ntp_fmt_ts(reftime));
	  offset += 8;

	} /* if tree */
	break;
  case MIP_REGISTRATION_REPLY:
	col_add_fstr(pinfo->cinfo, COL_INFO,
		       "Reg Reply: HoA=%s HA=%s, Code=%u",
		       ip_to_str(tvb_get_ptr(tvb,4,4)), 
		       ip_to_str(tvb_get_ptr(tvb,8,4)), 
		       tvb_get_guint8(tvb,1));

	if (tree) {
	  /* Add Subtree */
	  ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
	  mip_tree = proto_item_add_subtree(ti, ett_mip);

	  /* Type */
  	  proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
	  offset++;

	  /* Reply Code */
	  proto_tree_add_item(mip_tree, hf_mip_code, tvb, offset, 1, FALSE);
	  offset++;

	  /* Registration Lifetime */
	  proto_tree_add_item(mip_tree, hf_mip_life, tvb, offset, 2, FALSE);
	  offset += 2;

	  /* Home address */
	  proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* Home Agent Address */
	  proto_tree_add_item(mip_tree, hf_mip_haaddr, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* Identifier - assumed to be an NTP time here */
	  reftime = tvb_get_ptr(tvb, offset, 8);
	  proto_tree_add_bytes_format(mip_tree, hf_mip_ident, tvb, offset, 8,
				      reftime,
				      "Identification: %s",
				      ntp_fmt_ts(reftime));
	  offset += 8;
	} /* if tree */
	break;
  case MIP_NATT_TUNNEL_DATA:
	col_add_fstr(pinfo->cinfo, COL_INFO, "Tunnel Data: Next Header=%u",
		       tvb_get_guint8(tvb,1));

	if (tree) {
	  /* Add Subtree */
	  ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
	  mip_tree = proto_item_add_subtree(ti, ett_mip);

	  /* Type */
  	  proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
	  offset++;

	  /* Next Header */
	  proto_tree_add_item(mip_tree, hf_mip_nattt_nexthdr, tvb, offset, 1, FALSE);
	  offset++;

	  /* reserved */
	  proto_tree_add_item(mip_tree, hf_mip_nattt_reserved, tvb, offset, 2, FALSE);
	  offset += 2;
	} /* if tree */
	else {
	  offset += 4;
	}
	/* encapsulated payload */
	next_tvb = tvb_new_subset_remaining(tvb, 4);
	call_dissector(ip_handle, next_tvb, pinfo, mip_tree);
	offset += tvb_reported_length_remaining(tvb, offset);
	break;
  case MIP_REGISTRATION_REVOCATION:
	col_add_fstr(pinfo->cinfo, COL_INFO,
		       "Reg Revocation: HoA=%s HDA=%s FDA=%s",
		       ip_to_str(tvb_get_ptr(tvb,4,4)),
		       ip_to_str(tvb_get_ptr(tvb,8,4)),
		       ip_to_str(tvb_get_ptr(tvb,12,4)));

	if (tree) {
	  ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
	  mip_tree = proto_item_add_subtree(ti, ett_mip);

	  /* type */
	  proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
	  offset++;

	  /* reserved */
	  proto_tree_add_item(mip_tree, hf_mip_rev_reserved, tvb, offset, 1, FALSE);
	  offset++;

	  /* flags */
	  flags = tvb_get_ntohs(tvb, offset);
	  tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 2, flags);
	  flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_rev_a, tvb, offset, 2, flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_rev_i, tvb, offset, 2, flags);

	  /* reserved */
	  proto_tree_add_uint(flags_tree, hf_mip_rev_reserved, tvb, offset, 2, flags);
	  offset += 2;

	  /* home address */
	  proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* home domain address */
	  proto_tree_add_item(mip_tree, hf_mip_hda, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* foreign domain address */
	  proto_tree_add_item(mip_tree, hf_mip_fda, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* revocation identifier */
	  proto_tree_add_item(mip_tree, hf_mip_revid, tvb, offset, 4, FALSE);
	  offset += 4;
	} /* if tree */
	break;
  case MIP_REGISTRATION_REVOCATION_ACK:
	  col_add_fstr(pinfo->cinfo, COL_INFO, "Reg Revocation Ack: HoA=%s",
		       ip_to_str(tvb_get_ptr(tvb,4,4)));

	if (tree) {
	  ti = proto_tree_add_item(tree, proto_mip, tvb, offset, -1, FALSE);
	  mip_tree = proto_item_add_subtree(ti, ett_mip);

	  /* type */
	  proto_tree_add_uint(mip_tree, hf_mip_type, tvb, offset, 1, type);
	  offset++;

	  /* reserved */
	  proto_tree_add_item(mip_tree, hf_mip_ack_reserved, tvb, offset, 1, FALSE);
	  offset++;

	  /* flags */
	  flags = tvb_get_ntohs(tvb, offset);
	  tf = proto_tree_add_uint(mip_tree, hf_mip_flags, tvb, offset, 2, flags);
	  flags_tree = proto_item_add_subtree(tf, ett_mip_flags);
	  proto_tree_add_boolean(flags_tree, hf_mip_ack_i, tvb, offset, 2, flags);

	  /* reserved */
	  proto_tree_add_uint(flags_tree, hf_mip_ack_reserved, tvb, offset, 2, flags);
	  offset += 2;

	  /* home address */
	  proto_tree_add_item(mip_tree, hf_mip_homeaddr, tvb, offset, 4, FALSE);
	  offset += 4;

	  /* revocation identifier */
	  proto_tree_add_item(mip_tree, hf_mip_revid, tvb, offset, 4, FALSE);
	  offset += 4;
	} /* if tree */
	break;
  } /* End switch */

  if (tree) {
	if (tvb_reported_length_remaining(tvb, offset) > 0)
	  dissect_mip_extensions(tvb, offset, mip_tree);
  }
} /* dissect_mip */
Пример #11
0
static void
dissect_bacnet(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item *ti;
    proto_item *ct;
    proto_tree *bacnet_tree;
    proto_tree *control_tree;

    gint offset;
    guint8 bacnet_version;
    guint8 bacnet_control;
    guint8 bacnet_dlen;
    guint8 bacnet_slen;
    guint8 bacnet_mesgtyp;
    guint8 bacnet_rejectreason;
    guint8 bacnet_rportnum;
    guint8 bacnet_pinfolen;
    guint8 i;
    tvbuff_t *next_tvb;
    guint32 vendor_id;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "BACnet-NPDU");

    col_set_str(pinfo->cinfo, COL_INFO, "Building Automation and Control Network NPDU");

    offset = 0;
    bacnet_version = tvb_get_guint8(tvb, offset);
    bacnet_control = tvb_get_guint8(tvb, offset+1);

    /* I don't know the length of the NPDU yet; Setting the length after dissection */
    ti = proto_tree_add_item(tree, proto_bacnet, tvb, 0, -1, ENC_NA);

    bacnet_tree = proto_item_add_subtree(ti, ett_bacnet);

    proto_tree_add_uint_format_value(bacnet_tree, hf_bacnet_version, tvb,
                                     offset, 1,
                                     bacnet_version,"0x%02x (%s)",bacnet_version,
                                     (bacnet_version == 0x01)?"ASHRAE 135-1995":"unknown");
    offset ++;
    ct = proto_tree_add_uint(bacnet_tree, hf_bacnet_control,
                             tvb, offset, 1, bacnet_control);
    control_tree = proto_item_add_subtree(ct, ett_bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_net,
                           tvb, offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_res1, tvb,
                           offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_dest, tvb,
                           offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_res2, tvb,
                           offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_src, tvb,
                           offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_expect, tvb,
                           offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_high,
                           tvb, offset, 1, bacnet_control);
    proto_tree_add_boolean(control_tree, hf_bacnet_control_prio_low,
                           tvb, offset, 1, bacnet_control);
    offset ++;
    if (bacnet_control & BAC_CONTROL_DEST) { /* DNET, DLEN, DADR */
        proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                            tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;
        bacnet_dlen = tvb_get_guint8(tvb, offset);
        /* DLEN = 0 is broadcast on dest.network */
        if( bacnet_dlen == 0) {
            /* append to hf_bacnet_dlen: broadcast */
            proto_tree_add_uint_format_value(bacnet_tree,
                                             hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen,
                                             "%d indicates Broadcast on Destination Network",
                                             bacnet_dlen);
            offset ++;
            /* going to SNET */
        } else if (bacnet_dlen==6) {
            proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen,
                                tvb, offset, 1, bacnet_dlen);
            offset ++;
            /* Ethernet MAC */
            proto_tree_add_item(bacnet_tree,
                                hf_bacnet_dadr_eth, tvb, offset,
                                bacnet_dlen, ENC_NA);
            offset += bacnet_dlen;
        } else if (bacnet_dlen==1) {
            proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen,
                                tvb, offset, 1, bacnet_dlen);
            offset ++;
            /* MS/TP or ARCNET MAC */
            proto_tree_add_item(bacnet_tree,
                                hf_bacnet_dadr_mstp, tvb, offset,
                                bacnet_dlen, ENC_BIG_ENDIAN);
            offset += bacnet_dlen;
        } else if (bacnet_dlen<7) {
            proto_tree_add_uint(bacnet_tree, hf_bacnet_dlen,
                                tvb, offset, 1, bacnet_dlen);
            offset ++;
            /* Other MAC formats should be included here */
            proto_tree_add_item(bacnet_tree,
                                hf_bacnet_dadr_tmp, tvb, offset,
                                bacnet_dlen, ENC_NA);
            offset += bacnet_dlen;
        } else {
            proto_tree_add_uint_format_value(bacnet_tree,
                                             hf_bacnet_dlen, tvb, offset, 1, bacnet_dlen,
                                             "%d invalid!",
                                             bacnet_dlen);
        }
    }
    if (bacnet_control & BAC_CONTROL_SRC) { /* SNET, SLEN, SADR */
        /* SNET */
        proto_tree_add_uint(bacnet_tree, hf_bacnet_snet,
                            tvb, offset, 2, tvb_get_ntohs(tvb, offset));
        offset += 2;
        bacnet_slen = tvb_get_guint8(tvb, offset);
        if( bacnet_slen == 0) { /* SLEN = 0 invalid */
            proto_tree_add_uint_format_value(bacnet_tree,
                                             hf_bacnet_slen, tvb, offset, 1, bacnet_slen,
                                             "%d invalid!",
                                             bacnet_slen);
            offset ++;
        } else if (bacnet_slen==6) {
            /* SLEN */
            proto_tree_add_uint(bacnet_tree, hf_bacnet_slen,
                                tvb, offset, 1, bacnet_slen);
            offset ++;
            /* Ethernet MAC */
            proto_tree_add_item(bacnet_tree,
                                hf_bacnet_sadr_eth, tvb, offset,
                                bacnet_slen, ENC_NA);
            offset += bacnet_slen;
        } else if (bacnet_slen==1) {
            /* SLEN */
            proto_tree_add_uint(bacnet_tree, hf_bacnet_slen,
                                tvb, offset, 1, bacnet_slen);
            offset ++;
            /* MS/TP or ARCNET MAC */
            proto_tree_add_item(bacnet_tree,
                                hf_bacnet_sadr_mstp, tvb, offset,
                                bacnet_slen, ENC_BIG_ENDIAN);
            offset += bacnet_slen;
        } else if (bacnet_slen<6) { /* LON MAC */
            /* SLEN */
            proto_tree_add_uint(bacnet_tree, hf_bacnet_slen,
                                tvb, offset, 1, bacnet_slen);
            offset ++;
            /* Other MAC formats should be included here */
            proto_tree_add_item(bacnet_tree,
                                hf_bacnet_sadr_tmp, tvb, offset,
                                bacnet_slen, ENC_NA);
            offset += bacnet_slen;
        } else {
            proto_tree_add_uint_format_value(bacnet_tree,
                                             hf_bacnet_slen, tvb, offset, 1, bacnet_slen,
                                             "%d invalid!",
                                             bacnet_slen);
            offset ++;
        }
    }
    if (bacnet_control & BAC_CONTROL_DEST) { /* Hopcount */
        proto_tree_add_item(bacnet_tree, hf_bacnet_hopc,
                            tvb, offset, 1, ENC_BIG_ENDIAN);
        offset ++;
    }
    /* Network Layer Message Type */
    if (bacnet_control & BAC_CONTROL_NET) {
        bacnet_mesgtyp =  tvb_get_guint8(tvb, offset);
        proto_tree_add_uint_format_value(bacnet_tree,
                                         hf_bacnet_mesgtyp, tvb, offset, 1, bacnet_mesgtyp,
                                         "%02x (%s)", bacnet_mesgtyp,
                                         bacnet_mesgtyp_name(bacnet_mesgtyp));
        /* Put the NPDU Type in the info column */
        col_add_str(pinfo->cinfo, COL_INFO,
                    bacnet_mesgtyp_name(bacnet_mesgtyp));
        offset ++;
        /* Vendor ID
        * The standard says: "If Bit 7 of the control octet is 1 and
        * the Message Type field contains a value in the range
        * X'80' - X'FF', then a Vendor ID field shall be present (...)."
        * We should not go any further in dissecting the packet if it's
        * not present, but we don't know about that: No length field...
        */
        if (bacnet_mesgtyp > 0x7f) {
            /* Note: our next_tvb includes message type and vendor id! */
            next_tvb = tvb_new_subset_remaining(tvb, offset-1);
            vendor_id = tvb_get_ntohs(tvb, offset);
            proto_tree_add_uint(bacnet_tree, hf_bacnet_vendor, tvb,
                                offset, 2, vendor_id);
            offset += 2;	/* vendor_id */
            if (dissector_try_uint(bacnet_dissector_table,
                                   vendor_id, next_tvb, pinfo, bacnet_tree)) {
                /* we parsed it so skip over length and we are done */
                /* Note: offset has now been bumped for message type and vendor id so we take that out of our next_tvb size */
                offset += tvb_length(next_tvb) -3;
            }
        }
        /* Performance Index (in I-Could-Be-Router-To-Network) */
        if (bacnet_mesgtyp == BAC_NET_ICB_R) {
            proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                                tvb, offset, 2, ENC_BIG_ENDIAN);
            offset += 2;
            proto_tree_add_item(bacnet_tree, hf_bacnet_perf,
                                tvb, offset, 1, ENC_BIG_ENDIAN);
            offset ++;
        }
        /* Reason, DNET (in Reject-Message-To-Network) */
        if (bacnet_mesgtyp == BAC_NET_REJ) {
            bacnet_rejectreason = tvb_get_guint8(tvb, offset);
            proto_tree_add_uint_format_value(bacnet_tree,
                                             hf_bacnet_rejectreason,
                                             tvb, offset, 1,
                                             bacnet_rejectreason, "%d (%s)",
                                             bacnet_rejectreason,
                                             bacnet_rejectreason_name(bacnet_rejectreason));
            offset ++;
            proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                                tvb, offset, 2, ENC_BIG_ENDIAN);
            offset += 2;
        }
        /* N*DNET (in Router-Busy-To-Network,Router-Available-To-Network) */
        if ((bacnet_mesgtyp == BAC_NET_R_BUSY) ||
                (bacnet_mesgtyp == BAC_NET_WHO_R) ||
                (bacnet_mesgtyp == BAC_NET_R_AVA) ||
                (bacnet_mesgtyp == BAC_NET_IAM_R) ) {
            while(tvb_reported_length_remaining(tvb, offset) > 1 ) {
                proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                                    tvb, offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
            }
        }
        /* Initialize-Routing-Table */
        if ( (bacnet_mesgtyp == BAC_NET_INIT_RTAB) ||
                (bacnet_mesgtyp == BAC_NET_INIT_RTAB_ACK) ) {
            bacnet_rportnum = tvb_get_guint8(tvb, offset);
            /* number of ports */
            proto_tree_add_uint(bacnet_tree, hf_bacnet_rportnum,
                                tvb, offset, 1, bacnet_rportnum);
            offset ++;
            for(i=0; i<bacnet_rportnum; i++) {
                /* Connected DNET */
                proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                                    tvb, offset, 2, ENC_BIG_ENDIAN);
                offset += 2;
                /* Port ID */
                proto_tree_add_item(bacnet_tree, hf_bacnet_portid,
                                    tvb, offset, 1, ENC_BIG_ENDIAN);
                offset ++;
                /* Port Info Length */
                bacnet_pinfolen = tvb_get_guint8(tvb, offset);
                proto_tree_add_uint(bacnet_tree, hf_bacnet_pinfolen,
                                    tvb, offset, 1, bacnet_pinfolen);
                offset ++;
                proto_tree_add_item(bacnet_tree, hf_bacnet_pinfo, tvb, offset,
                                    bacnet_pinfolen, ENC_NA);
                offset += bacnet_pinfolen;
            }
        }
        /* Establish-Connection-To-Network */
        if (bacnet_mesgtyp == BAC_NET_EST_CON) {
            proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                                tvb, offset, 2, ENC_BIG_ENDIAN);
            offset += 2;
            proto_tree_add_item(bacnet_tree, hf_bacnet_term_time_value,
                                tvb, offset, 1, ENC_BIG_ENDIAN);
            offset ++;
        }
        /* Disconnect-Connection-To-Network */
        if (bacnet_mesgtyp == BAC_NET_DISC_CON) {
            proto_tree_add_item(bacnet_tree, hf_bacnet_dnet,
                                tvb, offset, 2, ENC_BIG_ENDIAN);
            offset += 2;
        }
    }
    /* Now set NPDU length */
    proto_item_set_len(ti, offset);

    /* dissect BACnet APDU */
    next_tvb = tvb_new_subset_remaining(tvb,offset);
    if (bacnet_control & BAC_CONTROL_NET) {
        /* Unknown function - dissect the payload as data */
        call_dissector(data_handle, next_tvb, pinfo, tree);
    } else {
        /* APDU - call the APDU dissector */
        call_dissector(bacapp_handle, next_tvb, pinfo, tree);
    }
}
Пример #12
0
/* Code to actually dissect the packets */
static void
dissect_wtp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    char          *szInfo;
    int            offCur        = 0;   /* current offset from start of WTP data */
    gint           returned_length, str_index = 0;

    unsigned char  b0;

    /* continuation flag */
    unsigned char  fCon;            /* Continue flag    */
    unsigned char  fRID;            /* Re-transmission indicator*/
    unsigned char  fTTR = '\0';        /* Transmission trailer    */
    guint          cbHeader       = 0;    /* Fixed header length    */
    guint          vHeader       = 0;    /* Variable header length*/
    int            abortType      = 0;

    /* Set up structures we'll need to add the protocol subtree and manage it */
    proto_item    *ti = NULL;
    proto_tree    *wtp_tree = NULL;

    char           pdut;
    char           clsTransaction = 3;
    int            numMissing = 0;        /* Number of missing packets in a negative ack */
    int            i;
    tvbuff_t      *wsp_tvb = NULL;
    guint8         psn = 0;        /* Packet sequence number*/
    guint16        TID = 0;        /* Transaction-Id    */
    int            dataOffset;
    gint           dataLen;

#define SZINFO_SIZE 256
    szInfo=(char *)wmem_alloc(wmem_packet_scope(), SZINFO_SIZE);

    b0 = tvb_get_guint8 (tvb, offCur + 0);
    /* Discover Concatenated PDUs */
    if (b0 == 0) {
        guint    c_fieldlen = 0;        /* Length of length-field    */
        guint    c_pdulen = 0;        /* Length of conc. PDU    */

        if (tree) {
            ti = proto_tree_add_item(tree, proto_wtp,
                    tvb, offCur, 1, ENC_NA);
            wtp_tree = proto_item_add_subtree(ti, ett_wtp_sub_pdu_tree);
            proto_item_append_text(ti, ", PDU concatenation");
        }
        offCur = 1;
        i = 1;
        while (offCur < (int) tvb_reported_length(tvb)) {
            tvbuff_t *wtp_tvb;
            /* The length of an embedded WTP PDU is coded as either:
             *    - a 7-bit value contained in one octet with highest bit == 0.
             *    - a 15-bit value contained in two octets (little endian)
             *      if the 1st octet has its highest bit == 1.
             * This means that this is NOT encoded as an uintvar-integer!!!
             */
            b0 = tvb_get_guint8(tvb, offCur + 0);
            if (b0 & 0x80) {
                c_fieldlen = 2;
                c_pdulen = ((b0 & 0x7f) << 8) | tvb_get_guint8(tvb, offCur + 1);
            } else {
                c_fieldlen = 1;
                c_pdulen = b0;
            }
            if (tree) {
                proto_tree_add_uint(wtp_tree, hf_wtp_header_sub_pdu_size,
                        tvb, offCur, c_fieldlen, c_pdulen);
            }
            if (i > 1) {
                col_append_str(pinfo->cinfo, COL_INFO, ", ");
            }
            /* Skip the length field for the WTP sub-tvb */
            wtp_tvb = tvb_new_subset_length(tvb, offCur + c_fieldlen, c_pdulen);
            dissect_wtp_common(wtp_tvb, pinfo, wtp_tree);
            offCur += c_fieldlen + c_pdulen;
            i++;
        }
        if (tree) {
            proto_item_append_text(ti, ", PDU count: %u", i);
        }
        return;
    }
    /* No concatenation */
    fCon = b0 & 0x80;
    fRID = retransmission_indicator(b0);
    pdut = pdu_type(b0);

#ifdef DEBUG
    printf("WTP packet %u: tree = %p, pdu = %s (%u) length: %u\n",
            pinfo->fd->num, tree,
            val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x"),
            pdut, tvb_captured_length(tvb));
#endif

    /* Develop the string to put in the Info column */
    returned_length =  g_snprintf(szInfo, SZINFO_SIZE, "WTP %s",
            val_to_str(pdut, vals_wtp_pdu_type, "Unknown PDU type 0x%x"));
    str_index += MIN(returned_length, SZINFO_SIZE-str_index);

    switch (pdut) {
        case INVOKE:
            fTTR = transmission_trailer(b0);
            TID = tvb_get_ntohs(tvb, offCur + 1);
            psn = 0;
            clsTransaction = transaction_class(tvb_get_guint8(tvb, offCur + 3));
            returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index,
                    " Class %d", clsTransaction);
            str_index += MIN(returned_length, SZINFO_SIZE-str_index);
            cbHeader = 4;
            break;

        case SEGMENTED_INVOKE:
        case SEGMENTED_RESULT:
            fTTR = transmission_trailer(b0);
            TID = tvb_get_ntohs(tvb, offCur + 1);
            psn = tvb_get_guint8(tvb, offCur + 3);
            if (psn != 0) {
                returned_length = g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index,
                        " (%u)", psn);
                str_index += MIN(returned_length, SZINFO_SIZE-str_index);
            }
            cbHeader = 4;
            break;

        case ABORT:
            cbHeader = 4;
            break;

        case RESULT:
            fTTR = transmission_trailer(b0);
            TID = tvb_get_ntohs(tvb, offCur + 1);
            psn = 0;
            cbHeader = 3;
            break;

        case ACK:
            cbHeader = 3;
            break;

        case NEGATIVE_ACK:
            /* Variable number of missing packets */
            numMissing = tvb_get_guint8(tvb, offCur + 3);
            cbHeader = numMissing + 4;
            break;

        default:
            break;
    };
    if (fRID) {
        /*returned_length =*/ g_snprintf(&szInfo[str_index], SZINFO_SIZE-str_index, " R" );
        /*str_index += MIN(returned_length, SZINFO_SIZE-str_index);*/
    };
    /* In the interest of speed, if "tree" is NULL, don't do any work not
       necessary to generate protocol tree items. */
    if (tree) {
#ifdef DEBUG
        fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader);
#endif
        /* NOTE - Length will be set when we process the TPI */
        ti = proto_tree_add_item(tree, proto_wtp, tvb, offCur, 0, ENC_NA);
#ifdef DEBUG
        fprintf(stderr, "dissect_wtp: (7) Returned from proto_tree_add_item\n");
#endif
        wtp_tree = proto_item_add_subtree(ti, ett_wtp);

        /* Code to process the packet goes here */
#ifdef DEBUG
        fprintf(stderr, "dissect_wtp: cbHeader = %d\n", cbHeader);
        fprintf(stderr, "dissect_wtp: offCur = %d\n", offCur);
#endif
        /* Add common items: only CON and PDU Type */
        proto_tree_add_item(
                wtp_tree,             /* tree */
                hf_wtp_header_flag_continue,     /* id */
                tvb,
                offCur,             /* start of highlight */
                1,                /* length of highlight*/
                b0                /* value */
                );
        proto_tree_add_item(wtp_tree, hf_wtp_header_pdu_type, tvb, offCur, 1, ENC_LITTLE_ENDIAN);

        switch(pdut) {
            case INVOKE:
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

                proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_version , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_TIDNew, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_flag_UP, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_Reserved, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_Inv_TransactionClass, tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_item_append_text(ti,
                        ", PDU: Invoke (%u)"
                        ", Transaction Class: %s (%u)",
                        INVOKE,
                        val_to_str_const(clsTransaction, vals_transaction_classes, "Undefined"),
                        clsTransaction);
                break;

            case RESULT:
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_item_append_text(ti, ", PDU: Result (%u)", RESULT);
                break;

            case ACK:
                proto_tree_add_item(wtp_tree, hf_wtp_header_Ack_flag_TVETOK, tvb, offCur, 1, ENC_BIG_ENDIAN);

                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_item_append_text(ti, ", PDU: ACK (%u)", ACK);
                break;

            case ABORT:
                abortType = tvb_get_guint8 (tvb, offCur) & 0x07;
                proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_type , tvb, offCur , 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

                if (abortType == PROVIDER) {
                    guint8 reason = tvb_get_guint8(tvb, offCur + 3);
                    proto_tree_add_item( wtp_tree, hf_wtp_header_Abort_reason_provider , tvb, offCur + 3 , 1, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti,
                            ", PDU: Abort (%u)"
                            ", Type: Provider (%u)"
                            ", Reason: %s (%u)",
                            ABORT,
                            PROVIDER,
                            val_to_str_const(reason, vals_abort_reason_provider, "Undefined"),
                            reason);
                }
                else if (abortType == USER) {
                    guint8 reason = tvb_get_guint8(tvb, offCur + 3);
                    proto_tree_add_item(wtp_tree, hf_wtp_header_Abort_reason_user , tvb, offCur + 3 , 1, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti,
                            ", PDU: Abort (%u)"
                            ", Type: User (%u)"
                            ", Reason: %s (%u)",
                            ABORT,
                            PROVIDER,
                            val_to_str_ext_const(reason, &vals_wsp_reason_codes_ext, "Undefined"),
                            reason);
                }
                break;

            case SEGMENTED_INVOKE:
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

                proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_item_append_text(ti,
                        ", PDU: Segmented Invoke (%u)"
                        ", Packet Sequence Number: %u",
                        SEGMENTED_INVOKE, psn);
                break;

            case SEGMENTED_RESULT:
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_Trailer, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

                proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                proto_item_append_text(ti,
                        ", PDU: Segmented Result (%u)"
                        ", Packet Sequence Number: %u",
                        SEGMENTED_RESULT, psn);
                break;

            case NEGATIVE_ACK:
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_RID, tvb, offCur, 1, ENC_LITTLE_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID_response, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(wtp_tree, hf_wtp_header_flag_TID, tvb, offCur + 1, 2, ENC_BIG_ENDIAN);

                proto_tree_add_item(wtp_tree, hf_wtp_header_missing_packets , tvb, offCur + 3, 1, ENC_LITTLE_ENDIAN);
                /* Iterate through missing packets */
                for (i = 0; i < numMissing; i++)
                {
                    proto_tree_add_item(wtp_tree, hf_wtp_header_sequence_number, tvb, offCur + 4 + i, 1, ENC_LITTLE_ENDIAN);
                }
                proto_item_append_text(ti,
                        ", PDU: Negative Ack (%u)"
                        ", Missing Packets: %u",
                        NEGATIVE_ACK, numMissing);
                break;

            default:
                break;
        };
        if (fRID) {
            proto_item_append_text(ti, ", Retransmission");
        }
    } else { /* tree is NULL */
#ifdef DEBUG
        fprintf(stderr, "dissect_wtp: (4) tree was %p\n", tree);
#endif
    }
    /* Process the variable part */
    if (fCon) {            /* Now, analyze variable part    */
        guint8    tCon;
        guint8    tByte;
        guint     tpiLen;
        tvbuff_t *tmp_tvb;

        vHeader = 0;        /* Start scan all over    */

        do {
            tByte = tvb_get_guint8(tvb, offCur + cbHeader + vHeader);
            tCon = tByte & 0x80;
            if (tByte & 0x04)    /* Long TPI    */
                tpiLen = 2 + tvb_get_guint8(tvb, offCur + cbHeader + vHeader + 1);
            else
                tpiLen = 1 + (tByte & 0x03);
            if (tree)
            {
                tmp_tvb = tvb_new_subset_length(tvb, offCur + cbHeader + vHeader, tpiLen);
                wtp_handle_tpi(wtp_tree, tmp_tvb);
            }
            vHeader += tpiLen;
        } while (tCon);
    } else {
        /* There is no variable part */
    }    /* End of variable part of header */

    /* Set the length of the WTP protocol part now we know the length of the
     * fixed and variable WTP headers */
    if (tree)
        proto_item_set_len(ti, cbHeader + vHeader);

#ifdef DEBUG
    fprintf( stderr, "dissect_wtp: cbHeader = %d\n", cbHeader );
#endif

    /*
     * Any remaining data ought to be WSP data (if not WTP ACK, NACK
     * or ABORT pdu), so, if we have any remaining data, and it's
     * not an ACK, NACK, or ABORT PDU, hand it off (defragmented) to the
     * WSP dissector.
     * Note that the last packet of a fragmented WTP message needn't
     * contain any data, so we allow payloadless packets to be
     * reassembled.  (XXX - does the reassembly code handle this
     * for packets other than the last packet?)
     *
     * Try calling a subdissector only if:
     *    - The WTP payload is ressembled in this very packet,
     *    - The WTP payload is not fragmented across packets.
     */
    dataOffset = offCur + cbHeader + vHeader;
    dataLen = tvb_reported_length_remaining(tvb, dataOffset);
    if ((dataLen >= 0) &&
            ! ((pdut==ACK) || (pdut==NEGATIVE_ACK) || (pdut==ABORT)))
    {
        /* Try to reassemble if needed, and hand over to WSP
         * A fragmented WTP packet is either:
         *    - An INVOKE with fTTR (transmission trailer) not set,
         *    - a SEGMENTED_INVOKE,
         *    - A RESULT with fTTR (transmission trailer) not set,
         *    - a SEGMENTED_RESULT.
         */
        if ( ( (pdut == SEGMENTED_INVOKE) || (pdut == SEGMENTED_RESULT)
                    || ( ((pdut == INVOKE) || (pdut == RESULT)) && (!fTTR) )
             ) && tvb_bytes_exist(tvb, dataOffset, dataLen) )
        {
            /* Try reassembling fragments */
            fragment_head *fd_wtp = NULL;
            guint32 reassembled_in = 0;
            gboolean save_fragmented = pinfo->fragmented;

            pinfo->fragmented = TRUE;
            fd_wtp = fragment_add_seq(&wtp_reassembly_table, tvb, dataOffset,
                    pinfo, TID, NULL, psn, dataLen, !fTTR, 0);
            /* XXX - fragment_add_seq() yields NULL unless Wireshark knows
             * that the packet is part of a reassembled whole. This means
             * that fd_wtp will be NULL as long as Wireshark did not encounter
             * (and process) the packet containing the last fragment.
             * This implies that Wireshark needs two passes over the data for
             * correct reassembly. At the first pass, a capture containing
             * three fragments plus a retransmssion of the last fragment
             * will progressively show:
             *
             *        Packet 1: (Unreassembled fragment 1)
             *        Packet 2: (Unreassembled fragment 2)
             *        Packet 3: (Reassembled WTP)
             *        Packet 4: (WTP payload reassembled in packet 3)
             *
             * However at subsequent evaluation (e.g., by applying a display
             * filter) the packet summary will show:
             *
             *        Packet 1: (WTP payload reassembled in packet 3)
             *        Packet 2: (WTP payload reassembled in packet 3)
             *        Packet 3: (Reassembled WTP)
             *        Packet 4: (WTP payload reassembled in packet 3)
             *
             * This is important to know, and also affects read filters!
             */
            wsp_tvb = process_reassembled_data(tvb, dataOffset, pinfo,
                    "Reassembled WTP", fd_wtp, &wtp_frag_items,
                    NULL, wtp_tree);
#ifdef DEBUG
            printf("WTP: Packet %u %s -> %d: wsp_tvb = %p, fd_wtp = %p, frame = %u\n",
                    pinfo->fd->num,
                    fd_wtp ? "Reassembled" : "Not reassembled",
                    fd_wtp ? fd_wtp->reassembled_in : -1,
                    wsp_tvb,
                    fd_wtp
                  );
#endif
            if (fd_wtp) {
                /* Reassembled */
                reassembled_in = fd_wtp->reassembled_in;
                if (pinfo->fd->num == reassembled_in) {
                    /* Reassembled in this very packet:
                     * We can safely hand the tvb to the WSP dissector */
                    call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
                } else {
                    /* Not reassembled in this packet */
                    col_append_fstr(pinfo->cinfo, COL_INFO,
                            "%s (WTP payload reassembled in packet %u)",
                            szInfo, fd_wtp->reassembled_in);

                    proto_tree_add_text(wtp_tree, tvb, dataOffset, -1, "Payload");
                }
            } else {
                /* Not reassembled yet, or not reassembled at all */
                col_append_fstr(pinfo->cinfo, COL_INFO,
                        "%s (Unreassembled fragment %u)",
                        szInfo, psn);
                proto_tree_add_text(wtp_tree, tvb, dataOffset, -1, "Payload");
            }
            /* Now reset fragmentation information in pinfo */
            pinfo->fragmented = save_fragmented;
        }
        else if ( ((pdut == INVOKE) || (pdut == RESULT)) && (fTTR) )
        {
            /* Non-fragmented payload */
            wsp_tvb = tvb_new_subset_remaining(tvb, dataOffset);
            /* We can safely hand the tvb to the WSP dissector */
            call_dissector(wsp_handle, wsp_tvb, pinfo, tree);
        }
        else
        {
            /* Nothing to hand to subdissector */
            col_append_str(pinfo->cinfo, COL_INFO, szInfo);
        }
    }
    else
    {
        /* Nothing to hand to subdissector */
        col_append_str(pinfo->cinfo, COL_INFO, szInfo);
    }
}
Пример #13
0
static void
dissect_nmpi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree	*nmpi_tree = NULL;
    proto_item	*ti;
    int		offset = 0;
    guint8		opcode;
    guint8		nmpi_name_type;
    char		name[(NETBIOS_NAME_LEN - 1)*4 + 1];
    int		name_type;
    char		node_name[(NETBIOS_NAME_LEN - 1)*4 + 1];
    /*int		node_name_type = 0;*/
    tvbuff_t	*next_tvb;

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

    if (tree) {
        ti = proto_tree_add_item(tree, proto_nmpi, tvb, offset, 68,
                                 ENC_NA);
        nmpi_tree = proto_item_add_subtree(ti, ett_nmpi);

        add_routers(nmpi_tree, tvb, offset);
    }
    offset += 32;

    /*
     * XXX - we don't use "node_name" or "node_name_type".
     */
    opcode = tvb_get_guint8(tvb, offset);
    nmpi_name_type = tvb_get_guint8(tvb, offset+1);
    name_type = get_netbios_name(tvb, offset+4, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
    /*node_name_type = */get_netbios_name(tvb, offset+20, node_name, (NETBIOS_NAME_LEN - 1)*4 + 1);

    switch (opcode) {

    case INAME_CLAIM:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Claim name %s<%02x>",
                     name, name_type);
        break;

    case INAME_DELETE:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Delete name %s<%02x>",
                     name, name_type);
        break;

    case INAME_QUERY:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Query name %s<%02x>",
                     name, name_type);
        break;

    case INAME_FOUND:
        col_add_fstr(pinfo->cinfo, COL_INFO, "Name %s<%02x> found",
                     name, name_type);
        break;

    case IMSG_HANGUP:
        col_add_fstr(pinfo->cinfo, COL_INFO,
                     "Messenger hangup on %s<%02x>", name, name_type);
        break;

    case IMSLOT_SEND:
        col_add_fstr(pinfo->cinfo, COL_INFO,
                     "Mailslot write to %s<%02x>", name, name_type);
        break;

    case IMSLOT_FIND:
        col_add_fstr(pinfo->cinfo, COL_INFO,
                     "Find mailslot name %s<%02x>", name, name_type);
        break;

    case IMSLOT_NAME:
        col_add_fstr(pinfo->cinfo, COL_INFO,
                     "Mailslot name %s<%02x> found", name, name_type);
        break;

    default:
        col_add_fstr(pinfo->cinfo, COL_INFO,
                     "Unknown NMPI op 0x%02x: name %s<%02x>",
                     opcode, name, name_type);
        break;
    }

    if (tree) {
        proto_tree_add_text(nmpi_tree, tvb, offset, 1,
                            "Opcode: %s (0x%02x)",
                            val_to_str_const(opcode, nmpi_opcode_vals, "Unknown"),
                            opcode);
        proto_tree_add_text(nmpi_tree, tvb, offset+1, 1,
                            "Name Type: %s (0x%02x)",
                            val_to_str_const(nmpi_name_type, nmpi_name_type_vals, "Unknown"),
                            nmpi_name_type);
        proto_tree_add_text(nmpi_tree, tvb, offset+2, 2,
                            "Message ID: 0x%04x",
                            tvb_get_letohs(tvb, offset+2));
        netbios_add_name("Requested name", tvb, offset+4, nmpi_tree);
        netbios_add_name("Source name", tvb, offset+20, nmpi_tree);
    }

    offset += 1 + 1 + 2 + NETBIOS_NAME_LEN + NETBIOS_NAME_LEN;

    if (opcode == IMSLOT_SEND && tvb_offset_exists(tvb, offset)) {
        next_tvb = tvb_new_subset_remaining(tvb, offset);
        dissect_netbios_payload(next_tvb, pinfo, tree);
    }
}
Пример #14
0
static int
dissect_nbipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
    gboolean	has_routes;
    proto_tree	*nbipx_tree = NULL;
    proto_item	*ti = NULL;
    int		offset = 0;
    guint8		packet_type;
    proto_tree	*name_type_flag_tree;
    proto_item	*tf;
    char		name[(NETBIOS_NAME_LEN - 1)*4 + 1];
    int		name_type;
    gboolean	has_payload;
    tvbuff_t	*next_tvb;
    ipxhdr_t *ipxh;

    /* Reject the packet if data is NULL */
    if (data == NULL)
        return 0;
    ipxh = (ipxhdr_t*)data;

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

    if (ipxh->ipx_type == IPX_PACKET_TYPE_WANBCAST) {
        /*
         * This is a WAN Broadcast packet; we assume it will have
         * 8 IPX addresses at the beginning.
         */
        has_routes = TRUE;
    } else {
        /*
         * This isn't a WAN Broadcast packet, but it still might
         * have the 8 addresses.
         *
         * If it's the right length for a name operation,
         * and, if we assume it has routes, the packet type
         * is a name operation, assume it has routes.
         *
         * NOTE: this will throw an exception if the byte that
         * would be the packet type byte if this has the 8
         * addresses isn't present; if that's the case, we don't
         * know how to interpret this packet, so we can't dissect
         * it anyway.
         */
        has_routes = FALSE;	/* start out assuming it doesn't */
        if (tvb_reported_length(tvb) == 50) {
            packet_type = tvb_get_guint8(tvb, offset + 32 + 1);
            switch (packet_type) {

            case NBIPX_FIND_NAME:
            case NBIPX_NAME_RECOGNIZED:
            case NBIPX_CHECK_NAME:
            case NBIPX_NAME_IN_USE:
            case NBIPX_DEREGISTER_NAME:
                has_routes = TRUE;
                break;
            }
        }
    }

    if (tree) {
        ti = proto_tree_add_item(tree, proto_nbipx, tvb, 0,
                                 -1, ENC_NA);
        nbipx_tree = proto_item_add_subtree(ti, ett_nbipx);
    }

    if (has_routes) {
        if (tree)
            add_routers(nbipx_tree, tvb, 0);
        offset += 32;
    }

    packet_type = tvb_get_guint8(tvb, offset + 1);

    switch (packet_type) {

    case NBIPX_FIND_NAME:
    case NBIPX_NAME_RECOGNIZED:
    case NBIPX_CHECK_NAME:
    case NBIPX_NAME_IN_USE:
    case NBIPX_DEREGISTER_NAME:
        name_type = get_netbios_name(tvb, offset+2, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s<%02x>",
                     val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"),
                     name, name_type);

        if (nbipx_tree) {
            tf = proto_tree_add_item(nbipx_tree, hf_nbipx_name_flags, tvb, offset, 1, ENC_LITTLE_ENDIAN);
            name_type_flag_tree = proto_item_add_subtree(tf, ett_nbipx_name_type_flags);

            proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_group, tvb, offset, 1, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_in_use, tvb, offset, 1, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_registered, tvb, offset, 1, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_duplicated, tvb, offset, 1, ENC_LITTLE_ENDIAN);
            proto_tree_add_item(name_type_flag_tree, hf_nbipx_name_flags_deregistered, tvb, offset, 1, ENC_LITTLE_ENDIAN);
        }
        offset += 1;

        proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type);
        offset += 1;

        if (nbipx_tree)
            netbios_add_name("Name", tvb, offset, nbipx_tree);
        offset += NETBIOS_NAME_LEN;

        /*
         * No payload to be interpreted by another protocol.
         */
        has_payload = FALSE;
        break;

    case NBIPX_SESSION_DATA:
    case NBIPX_SESSION_END:
    case NBIPX_SESSION_END_ACK:
        col_set_str(pinfo->cinfo, COL_INFO,
                    val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"));

        dissect_conn_control(tvb, offset, nbipx_tree);
        offset += 1;

        proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type);
        offset += 1;

        proto_tree_add_item(nbipx_tree, hf_nbipx_session_src_conn_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;

        proto_tree_add_item(nbipx_tree, hf_nbipx_session_dest_conn_id, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;

        proto_tree_add_item(nbipx_tree, hf_nbipx_session_send_seq_number, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;

        proto_tree_add_item(nbipx_tree, hf_nbipx_session_total_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;

        proto_tree_add_item(nbipx_tree, hf_nbipx_session_offset, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;

        proto_tree_add_item(nbipx_tree, hf_nbipx_session_data_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;

        proto_tree_add_item(nbipx_tree, hf_nbipx_session_recv_seq_number, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;

        proto_tree_add_item(nbipx_tree, hf_nbipx_session_bytes_received, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        offset += 2;

        /*
         * We may have payload to dissect.
         */
        has_payload = TRUE;
        break;

    case NBIPX_DIRECTED_DATAGRAM:
        col_set_str(pinfo->cinfo, COL_INFO,
                    val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"));

        dissect_conn_control(tvb, offset, nbipx_tree);
        offset += 1;

        proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type);
        offset += 1;

        if (nbipx_tree)
            netbios_add_name("Receiver's Name", tvb, offset,
                             nbipx_tree);
        offset += NETBIOS_NAME_LEN;

        if (nbipx_tree)
            netbios_add_name("Sender's Name", tvb, offset,
                             nbipx_tree);
        offset += NETBIOS_NAME_LEN;

        /*
         * We may have payload to dissect.
         */
        has_payload = TRUE;
        break;

    default:
        col_set_str(pinfo->cinfo, COL_INFO,
                    val_to_str_const(packet_type, nbipx_data_stream_type_vals, "Unknown"));

        /*
         * We don't know what the first byte is.
         */
        offset += 1;

        /*
         * The second byte is a data stream type byte.
         */
        proto_tree_add_uint(nbipx_tree, hf_nbipx_packettype, tvb, offset, 1, packet_type);
        offset += 1;

        /*
         * We don't know what the rest of the packet is.
         */
        has_payload = FALSE;
    }

    /*
     * Set the length of the NBIPX tree item.
     */
    if (ti != NULL)
        proto_item_set_len(ti, offset);

    if (has_payload && tvb_offset_exists(tvb, offset)) {
        next_tvb = tvb_new_subset_remaining(tvb, offset);
        dissect_netbios_payload(next_tvb, pinfo, tree);
    }

    return tvb_length(tvb);
}
Пример #15
0
static void
dissect_wai_data(tvbuff_t *tvb, proto_tree *tree, guint8 subtype, guint16 lenx)
{
    proto_item  *data_item;
    proto_tree  *data_tree;
    const gchar *type_name;

    data_item = proto_tree_add_item(tree, hf_wai_data, tvb, 0, lenx, ENC_NA);
    data_tree = proto_item_add_subtree (data_item, ett_wai_data);

    type_name = val_to_str_ext_const(subtype, &wai_subtype_names_ext, "Unknown type");

    proto_item_set_text(data_item, "%s data (%d bytes)", type_name, lenx);

    switch (subtype) {
        case WAI_SUB_PRE_AUTHENTICATION:
        {
            /* Chapter 8.1.4.6 Preauthentication [ref: 1] */
            dissect_flag(tvb, 0, data_tree);
            dissect_uskid(tvb, 1, data_tree);
            dissect_addid(tvb, 2, data_tree);
            dissect_counter(tvb, 14, data_tree);
            dissect_message_auth_code(tvb, 30, data_tree);
            break;
        }
        case WAI_SUB_STAKEY_REQ:
        {
            /* Chapter 8.1.4.5 STAKey Establishment procedure [ref: 1] */
            dissect_flag(tvb, 0, data_tree);
            proto_tree_add_item(data_tree, hf_wai_sta_key_id, tvb, 1, 1, ENC_BIG_ENDIAN);
            dissect_uskid(tvb, 2, data_tree);
            dissect_addid(tvb, 3, data_tree);
            dissect_counter(tvb, 15, data_tree);
            dissect_message_auth_code(tvb, 31, data_tree);
            break;
        }
        case WAI_SUB_AUTH_ACTIVATION:
        {
            /* Chapter 8.1.4.2.1 WAI Authentication Activation  [ref: 1] */
            guint16 offset = 0;

            dissect_flag(tvb, offset, data_tree);
            offset += 1;
            dissect_authentication_id(tvb, offset, data_tree);
            offset += 32;
            offset += dissect_identity(tvb, offset, data_tree, "Local ASU ");
            offset += dissect_certificate(tvb, offset, data_tree, "STE AE ");
            dissect_ecdh_parameter(tvb, offset, data_tree);
            break;
        }
        case WAI_SUB_ACCESS_AUTH_REQ:
        {
            /* Chapter 8.1.4.2.2 Access WAI Authentication Request  [ref: 1] */
            guint16 offset = 0;
            guint8  optional_field;

            optional_field = tvb_get_guint8(tvb, 0) & FLAG_BIT3;

            dissect_flag(tvb, offset, data_tree);
            offset += 1;
            dissect_authentication_id(tvb, offset, data_tree);
            offset += 32;
            offset += dissect_challenge(tvb, offset, data_tree, "ASUE ");
            offset += dissect_key_data(tvb, offset, data_tree, "ASUE ");
            offset += dissect_identity(tvb, offset, data_tree, "STA AE ");
            offset += dissect_certificate(tvb, offset, data_tree, "STA ASUE ");
            offset += dissect_ecdh_parameter(tvb, offset, data_tree);

            if (optional_field) {
                offset += dissect_identity_list(tvb, offset, data_tree);
            }

            dissect_signature(tvb, offset, data_tree, "ASUE Signature");
            break;
        }
        case WAI_SUB_ACCESS_AUTH_RESP:
        {
            /* Chapter 8.1.4.2.5 Access WAI Authentication Response  [ref: 1] */
            guint16 offset = 0;
            guint8  optional_field;

            optional_field = tvb_get_guint8(tvb, 0) & FLAG_BIT3;

            dissect_flag(tvb, offset, data_tree);
            offset += 1;
            offset += dissect_challenge(tvb, offset, data_tree, "ASUE ");
            offset += dissect_challenge(tvb, offset, data_tree, "AE ");
            proto_tree_add_item(data_tree, hf_wai_access_res, tvb, offset, 1, ENC_BIG_ENDIAN);
            offset += 1;
            offset += dissect_key_data(tvb, offset, data_tree, "ASUE ");
            offset += dissect_key_data(tvb, offset, data_tree, "AE ");
            offset += dissect_identity(tvb, offset, data_tree, "STA AE ");
            offset += dissect_identity(tvb, offset, data_tree, "STA ASUE ");

            if (optional_field) {
                offset += dissect_multiple_certificate(tvb, offset, data_tree);
            }

            offset += dissect_signature(tvb, offset, data_tree, "AE Signature");
            break;
        }
        case WAI_SUB_CERT_AUTH_REQ:
        {
            /* Chapter 8.1.4.2.3 Certificate Authentication Request  [ref: 1] */
            guint16 offset = 0;

            dissect_addid(tvb, offset, data_tree);
            offset += 12;
            offset += dissect_challenge(tvb, offset, data_tree, "AE ");
            offset += dissect_challenge(tvb, offset, data_tree, "ASUE ");
            offset += dissect_certificate(tvb, offset, data_tree, "STE ASUE ");
            offset += dissect_certificate(tvb, offset, data_tree, "STE AE ");
            offset += dissect_multiple_certificate(tvb, offset, data_tree);
            break;
        }
        case WAI_SUB_CERT_AUTH_RESP:
        {
            /* Chapter 8.1.4.2.4 Certificate Authentication Response  [ref: 1] */
            guint16 offset = 0;

            dissect_addid(tvb, offset, data_tree);
            offset += 12;
            offset += dissect_multiple_certificate(tvb, offset, data_tree);
            offset += dissect_signature(tvb, offset, data_tree, "Server Signature trusted by ASUE");
            offset += dissect_signature(tvb, offset, data_tree, "Server Signature trusted by AE");
            break;
        }
        case WAI_SUB_UNICAST_KEY_REQ:
        {
            /* Chapter 8.1.4.3.1 Unicast Key Negotiation Request [ref: 1] */
            dissect_flag(tvb, 0, data_tree);
            dissect_bkid(tvb, 1, data_tree);
            dissect_uskid(tvb, 17, data_tree);
            dissect_addid(tvb, 18, data_tree);
            dissect_challenge(tvb, 30, data_tree , "AE ");
            break;
        }
        case WAI_SUB_UNICAST_KEY_RESP:
        {
            /* Chapter 8.1.4.3.2 Unicast Key Negotiation Response [ref: 1] */
            tvbuff_t *next_tvb;
            guint     length = 0;

            dissect_flag(tvb, 0, data_tree);
            dissect_bkid(tvb, 1, data_tree);
            dissect_uskid(tvb, 17, data_tree);
            dissect_addid(tvb, 18, data_tree);
            dissect_challenge(tvb, 30, data_tree, "ASUE ");
            dissect_challenge(tvb, 62, data_tree, "AE ");

            next_tvb = tvb_new_subset_remaining(tvb, 96);
            length = tvb_reported_length(next_tvb);

            dissect_wie(next_tvb, 0, length-20, data_tree);
            dissect_message_auth_code(next_tvb, length-20, data_tree);
            break;
        }
        case WAI_SUB_UNICAST_KEY_CONFIRM:
        {
            /* Chapter 8.1.4.3.3 Unicast Key Negotiation Confirmation [ref: 1] */
            tvbuff_t *next_tvb;
            guint     length = 0;

            dissect_flag(tvb, 0, data_tree);
            dissect_bkid(tvb, 1, data_tree);
            dissect_uskid(tvb, 17, data_tree);
            dissect_addid(tvb, 18, data_tree);
            dissect_challenge(tvb, 30, data_tree, "ASUE ");

            next_tvb = tvb_new_subset_remaining(tvb, 62);
            length = tvb_reported_length(next_tvb);

            dissect_wie(next_tvb, 0, length-20, data_tree);
            dissect_message_auth_code(next_tvb, length-20, data_tree);
            break;
        }
        case WAI_SUB_MULTICAST_ANNOUNCE:
        {
            /* Chapter 8.1.4.4.1 Multicast Key/STAKey Announcement [ref: 1] */
            guint16 offset = 0;

            dissect_flag(tvb, offset, data_tree);
            offset += 1;
            dissect_mskid(tvb, offset, data_tree);
            offset += 1;
            dissect_uskid(tvb, offset, data_tree);
            offset += 1;
            dissect_addid(tvb, offset, data_tree);
            offset += 12;
            proto_tree_add_item(data_tree, hf_wai_data_pack_num, tvb, offset, 16, ENC_NA);
            offset += 16;
            dissect_key_announcement_identifier(tvb, offset, data_tree);
            offset += 16;
            offset += dissect_key_data(tvb, offset, data_tree, NULL);
            dissect_message_auth_code(tvb, offset, data_tree);
            break;
        }
        case WAI_SUB_MULTICAST_ANNOUNCE_RESP:
        {
            /* Chapter 8.1.4.4.2 Multicast Key/STAKey Announcement Response [ref: 1] */
            dissect_flag(tvb,  0, data_tree);
            dissect_mskid(tvb, 1, data_tree);
            dissect_uskid(tvb, 2, data_tree);
            dissect_addid(tvb, 3, data_tree);
            dissect_key_announcement_identifier(tvb, 15, data_tree);
            dissect_message_auth_code(tvb, 31, data_tree);
            break;
        }
        default:
            break;
    }
}
static void
dissect_prism(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree *prism_tree = NULL, *prism_did_tree = NULL;
    proto_item *ti = NULL, *ti_did = NULL;
    tvbuff_t *next_tvb;
    int offset;
    guint32 msgcode, msglen, did;
    guint16 status;
    guint8 *devname_p;

    offset = 0;
    did = 0;

    /* handle the AVS header */
    msgcode = tvb_get_ntohl(tvb, offset);
    if ((msgcode == WLANCAP_MAGIC_COOKIE_V1) ||
        (msgcode == WLANCAP_MAGIC_COOKIE_V2)) {
      call_dissector(wlancap_handle, tvb, pinfo, tree);
      return;
    }

    /*
     * If we don't see a valid message type, assume the Prism or AVS
     * header was omitted and just hand off to the 802.11 dissector;
     * at least one capture has AVS headers on some packets and no
     * radio headers on others (incoming vs. outgoing?).
     *
     * XXX - check for both byte orders and use that to determine
     * the byte order of the fields in the Prism header?
     */
    msgcode = tvb_get_letohl(tvb, offset);
    if ((msgcode != PRISM_TYPE1_MSGCODE) &&
        (msgcode != PRISM_TYPE2_MSGCODE)) {
        call_dissector(ieee80211_handle, tvb, pinfo, tree);
        return;
    }

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

    if(tree) {
        ti = proto_tree_add_item(tree, proto_prism, tvb, 0, 144, ENC_NA);
        prism_tree = proto_item_add_subtree(ti, ett_prism);
    }

    /* Message Code */
    if(tree) {
        proto_tree_add_item(prism_tree, hf_ieee80211_prism_msgcode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
    }
    msgcode = tvb_get_letohl(tvb, offset);
    offset += 4;

    /* Message Length */
    if(tree) {
        proto_tree_add_item(prism_tree, hf_ieee80211_prism_msglen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
    }
    msglen = tvb_get_letohl(tvb, offset);
    offset += 4;

    /* Device Name */
    if(tree) {
       proto_tree_add_item(prism_tree, hf_ieee80211_prism_devname, tvb, offset, 16, ENC_ASCII|ENC_NA);
    }
    devname_p = tvb_get_ephemeral_string(tvb, offset, 16);
    offset += 16;

    col_add_fstr(pinfo->cinfo, COL_INFO, "Device: %s, Message 0x%x, Length %d", devname_p, msgcode, msglen);


    while(offset < PRISM_HEADER_LENGTH)
    {
        /* DID */
        if(tree) {
            ti_did = proto_tree_add_item(prism_tree, hf_ieee80211_prism_did, tvb, offset, 12, ENC_NA);
            prism_did_tree = proto_item_add_subtree(ti_did, ett_prism_did);

            proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_type, tvb, offset, 4, ENC_LITTLE_ENDIAN);
            did = tvb_get_letohl(tvb, offset);
            proto_item_append_text(ti_did, " %s", val_to_str(did, prism_did_vals, "Unknown %x") );
        }
        offset += 4;


        /* Status */
        status = tvb_get_letohs(tvb, offset);
        if(tree) {
            proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_status, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        }
        offset += 2;

        /* Length */
        if(tree) {
            proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_length, tvb, offset, 2, ENC_LITTLE_ENDIAN);
        }
        offset += 2;

        /* Data, if present... */
        if (status == 0) {
            switch(did){
              case PRISM_TYPE1_HOSTTIME:
              case PRISM_TYPE2_HOSTTIME:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_hosttime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) );
                }
              break;

              case PRISM_TYPE1_MACTIME:
              case PRISM_TYPE2_MACTIME:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_mactime, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) );
                }
              break;

              case PRISM_TYPE1_CHANNEL:
              case PRISM_TYPE2_CHANNEL:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_channel, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) );
                }
                col_add_fstr(pinfo->cinfo, COL_FREQ_CHAN, "%u", tvb_get_letohl(tvb, offset));
              break;

              case PRISM_TYPE1_RSSI:
              case PRISM_TYPE2_RSSI:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rssi, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
                }
                col_add_fstr(pinfo->cinfo, COL_RSSI, "%d", tvb_get_letohl(tvb, offset));
              break;

              case PRISM_TYPE1_SQ:
              case PRISM_TYPE2_SQ:
                 if(tree){
                      proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_sq, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                      proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
                }
              break;

              case PRISM_TYPE1_SIGNAL:
              case PRISM_TYPE2_SIGNAL:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_signal, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
                }
              break;

              case PRISM_TYPE1_NOISE:
              case PRISM_TYPE2_NOISE:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_noise, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
                }
              break;

              case PRISM_TYPE1_RATE:
              case PRISM_TYPE2_RATE:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_rate, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " %s Mb/s", prism_rate_return(tvb_get_letohl(tvb, offset)) );
                }
                col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%s", prism_rate_return(tvb_get_letohl(tvb, offset)) );
              break;

              case PRISM_TYPE1_ISTX:
              case PRISM_TYPE2_ISTX:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_istx, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " 0x%x", tvb_get_letohl(tvb, offset) );
                }
              break;

              case PRISM_TYPE1_FRMLEN:
              case PRISM_TYPE2_FRMLEN:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_frmlen, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                    proto_item_append_text(ti_did, " %d", tvb_get_letohl(tvb, offset) );
                }
              break;

              default:
                if(tree){
                    proto_tree_add_item(prism_did_tree, hf_ieee80211_prism_did_unknown, tvb, offset, 4, ENC_LITTLE_ENDIAN);
                }
              break;
            }
        }
        offset += 4;
    }

    /* dissect the 802.11 header next */
    next_tvb = tvb_new_subset_remaining(tvb, offset);
    call_dissector(ieee80211_handle, next_tvb, pinfo, tree);
}
Пример #17
0
static void
dissect_wai(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
/* Format of WAPI protocol packet in WAI authentication system

0      2      3         4         6         8        10        11      12
-------------------------------------------------------------------------------
| Ver. | Type | Subtype | Reserved | Length | packet  |  fragm. | flag | data |
|                                           | seq. no | seq. no |             |
|-----------------------------------------------------------------------------|
Figure 18 from [ref:1]
*/
#define WAI_MESSAGE_LENGTH 12   /*Length of all fields without 'Data' field*/
#define WAI_DATA_OFFSET    WAI_MESSAGE_LENGTH
    guint16        version;
    guint8         subtype;
    guint16        length;
    guint16        packet_num;
    guint8         fragment_num;
    guint8         flags;
    fragment_data *frag_msg;
    proto_tree    *wai_tree     = NULL;
    tvbuff_t      *next_tvb;
    tvbuff_t      *new_tvb;
    const gchar   *subtype_name = "Unknown type";

    length = tvb_get_ntohs(tvb, 6)-WAI_MESSAGE_LENGTH;
    subtype = tvb_get_guint8(tvb, 3);

    /* quick sanity check */
    if ((length != tvb_reported_length (tvb)-WAI_MESSAGE_LENGTH) ||
        (subtype > WAI_SUB_MULTICAST_ANNOUNCE_RESP)) {
        return;
    }

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "WAI");
    col_clear(pinfo->cinfo, COL_INFO);
    version = tvb_get_ntohs(tvb, 0);

    if (version == 1) {
        subtype_name = val_to_str_ext_const(subtype, &wai_subtype_names_ext, "Unknown type");
    }
    col_append_fstr(pinfo->cinfo, COL_INFO, "%s", subtype_name);

    /* Field lengths and offsets in WAI protocol described above */
    packet_num   = tvb_get_ntohs(tvb, 8);
    fragment_num = tvb_get_guint8(tvb, 10);
    flags        = tvb_get_guint8(tvb, 11);

    if (tree) {
        proto_item *wai_item;

        wai_item = proto_tree_add_item(tree, proto_wai, tvb, 0, -1, ENC_NA);

        proto_item_set_text (wai_item, "WAI Protocol (%s)",
                                val_to_str_ext_const(subtype, &wai_subtype_names_ext, "Unknown type"));
        wai_tree = proto_item_add_subtree(wai_item, ett_wai);

        /* Field lengths and offsets in WAI protocol described above */
        proto_tree_add_item(wai_tree, hf_wai_version,   tvb, 0,  2, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_type,      tvb, 2,  1, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_subtype,   tvb, 3,  1, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_reserved,  tvb, 4,  2, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_length,    tvb, 6,  2, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_seq,       tvb, 8,  2, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_fragm_seq, tvb, 10, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(wai_tree, hf_wai_flag,      tvb, 11, 1, ENC_BIG_ENDIAN);
    }

    frag_msg =  fragment_add_seq_check (tvb, WAI_DATA_OFFSET, pinfo,
                                        packet_num,
                                        wai_fragment_table,
                                        wai_reassembled_table,
                                        fragment_num,
                                        length,
                                        flags);

    next_tvb = tvb_new_subset_remaining(tvb, WAI_DATA_OFFSET);

    /* Replace INFO column if message is fragmented and call data_handle */
    if (flags) {
        col_add_fstr(pinfo->cinfo, COL_INFO,
                     "Fragment (%d) of message, data not dissected", fragment_num);

        process_reassembled_data(tvb, WAI_DATA_OFFSET, pinfo,
                                 "Reassembled WAI", frag_msg, &wai_frag_items,
                                 NULL, wai_tree);

        call_dissector(data_handle, next_tvb, pinfo, tree);
    } else {
        /* If this is the last fragment of fragmented message, then reassamble and dissect
           otherwise only dissect */
        if (fragment_num > 0) {
            new_tvb = process_reassembled_data(tvb, WAI_DATA_OFFSET, pinfo,
                                               "Reassembled WAI", frag_msg, &wai_frag_items,
                                               NULL, wai_tree);

            if (new_tvb) {
                col_add_str(pinfo->cinfo, COL_INFO, "Last fragment of message, data dissected");
                col_append_sep_str(pinfo->cinfo, COL_INFO, ": ", subtype_name);
                next_tvb=new_tvb;
                length = tvb_reported_length (next_tvb);
            }
        }
        /* dissect Data field of WAI packet */
        if (tree) {
            dissect_wai_data(next_tvb, wai_tree, subtype, length);
        }
    }

}
Пример #18
0
static void
dissect_ax25_nol3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree )
{
    proto_item *ti;
    proto_tree *ax25_nol3_tree;
    char       *info_buffer;
    int         offset;
    tvbuff_t   *next_tvb = NULL;
    guint8      dti      = 0;
    gboolean    dissected;

    info_buffer = (char *)wmem_alloc( wmem_packet_scope(), STRLEN );
    info_buffer[0] = '\0';

    col_set_str( pinfo->cinfo, COL_PROTOCOL, "AX.25-NoL3");

    col_clear( pinfo->cinfo, COL_INFO);

    offset = 0;
    g_snprintf( info_buffer, STRLEN, "Text" );

    if ( gPREF_APRS )
    {
        dti = tvb_get_guint8( tvb, offset );
        if ( isaprs( dti ) )
            g_snprintf( info_buffer, STRLEN, "APRS" );
    }
    if ( gPREF_DX )
    {
        if ( tvb_get_guint8( tvb, offset ) == 'D' && tvb_get_guint8( tvb, offset + 1 ) == 'X' )
            g_snprintf( info_buffer, STRLEN, "DX cluster" );
    }

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

    /* Call sub-dissectors here */

    if ( parent_tree )
    {
        /* create display subtree for the protocol */
        ti = proto_tree_add_protocol_format( parent_tree,
                                             proto_ax25_nol3,
                                             tvb,
                                             0,
                                             -1,
                                             "AX.25 No Layer 3 - (%s)", info_buffer );
        ax25_nol3_tree = proto_item_add_subtree( ti, ett_ax25_nol3 );

        next_tvb = tvb_new_subset_remaining(tvb, offset);
        dissected = FALSE;
        if ( gPREF_APRS )
        {
            if ( isaprs( dti ) )
            {
                dissected = TRUE;
                call_dissector( aprs_handle , next_tvb, pinfo, ax25_nol3_tree );
            }
        }
        if ( gPREF_DX )
        {
            if ( tvb_get_guint8( tvb, offset ) == 'D' && tvb_get_guint8( tvb, offset + 1 ) == 'X' )
            {
                dissected = TRUE;
                dissect_dx( next_tvb, pinfo, ax25_nol3_tree );
            }
        }
        if ( ! dissected )
            call_dissector( default_handle , next_tvb, pinfo, ax25_nol3_tree );

    }
}
Пример #19
0
/*
 * Dissect an SPDU.
 */
static int
dissect_spdu(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
    gboolean tokens, gboolean connectionless)
{
	gboolean has_user_information = FALSE;
	guint8 type;
	proto_item *ti = NULL;
	proto_tree *ses_tree = NULL;
	int len_len;
	guint16 parameters_len;
	tvbuff_t *next_tvb;
	void *save_private_data;
	guint32 *pres_ctx_id = NULL;
	struct SESSION_DATA_STRUCTURE session;

	/*
	 * Get SPDU type.
	 */
	type = tvb_get_guint8(tvb, offset);
	session.spdu_type = type;
	session.abort_type = SESSION_NO_ABORT;
	session.ros_op = 0;
	session.rtse_reassemble = FALSE;

	if(connectionless) {
	  	if (check_col(pinfo->cinfo, COL_INFO))
			col_add_str(pinfo->cinfo, COL_INFO,
			    val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
		if (tree) {
			ti = proto_tree_add_item(tree, proto_clses, tvb, offset,
				-1, FALSE);
			ses_tree = proto_item_add_subtree(ti, ett_ses);
			proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
				offset, 1, type);
		}
		has_user_information = TRUE;
	}
	else if (tokens) {
	  	if (check_col(pinfo->cinfo, COL_INFO))
			col_add_str(pinfo->cinfo, COL_INFO,
			    val_to_str(type, ses_category0_vals, "Unknown SPDU type (0x%02x)"));
		if (tree) {
			ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
			    -1, FALSE);
			ses_tree = proto_item_add_subtree(ti, ett_ses);
			proto_tree_add_uint(ses_tree, hf_ses_type_0, tvb,
			    offset, 1, type);
		}
	} else {
	  	if (check_col(pinfo->cinfo, COL_INFO))
			col_add_str(pinfo->cinfo, COL_INFO,
			    val_to_str(type, ses_vals, "Unknown SPDU type (0x%02x)"));
		if (tree) {
			ti = proto_tree_add_item(tree, proto_ses, tvb, offset,
				-1, FALSE);
			ses_tree = proto_item_add_subtree(ti, ett_ses);
			proto_tree_add_uint(ses_tree, hf_ses_type, tvb,
				offset, 1, type);
		}

		/*
		 * Might this SPDU have a User Information field?
		 */
		switch (type) {
		case SES_DATA_TRANSFER:
		case SES_EXPEDITED:
		case SES_TYPED_DATA:
			has_user_information = TRUE;
			break;
		case SES_MAJOR_SYNC_POINT:
			pres_ctx_id = p_get_proto_data (pinfo->fd, proto_ses);
			if (ses_rtse_reassemble != 0 && !pres_ctx_id) {
				/* First time visited - save pres_ctx_id */
				pres_ctx_id = se_alloc (sizeof (guint32));
				*pres_ctx_id = ses_pres_ctx_id;
				p_add_proto_data (pinfo->fd, proto_ses, pres_ctx_id);
			}
			if (pres_ctx_id) {
				session.pres_ctx_id = *pres_ctx_id;
				session.rtse_reassemble = TRUE;
				has_user_information = TRUE;
			}
			ses_rtse_reassemble = FALSE;
			break;
		}
	}
	offset++;

	/* get length of SPDU parameter field */
	parameters_len = get_item_len(tvb, offset, &len_len);
	if (tree)
		proto_tree_add_uint(ses_tree, hf_ses_length, tvb, offset,
		    len_len, parameters_len);
	offset += len_len;

	/* Dissect parameters. */
	if (!dissect_parameters(tvb, offset, parameters_len, tree, ses_tree,
	    pinfo, &session))
		has_user_information = FALSE;
	offset += parameters_len;
	
	proto_item_set_end(ti, tvb, offset);

	/* Dissect user information, if present */
	if (has_user_information) {
		if (tvb_reported_length_remaining(tvb, offset) > 0 || type == SES_MAJOR_SYNC_POINT) {
			next_tvb = tvb_new_subset_remaining(tvb, offset);
			if(!pres_handle)
			{
				call_dissector(data_handle, next_tvb, pinfo,
					tree);
			}
			else
			{
				/*   save type of session pdu. We'll need it in the presentation dissector  */
				save_private_data = pinfo->private_data;
				pinfo->private_data = &session;
				call_dissector(pres_handle, next_tvb, pinfo,
					tree);
				pinfo->private_data = save_private_data;
			}

			/*
			 * No more SPDUs to dissect.  Set the offset to the
			 * end of the tvbuff.
			 */
			offset = tvb_length(tvb);
			if (session.rtse_reassemble && type == SES_DATA_TRANSFER) {
				ses_pres_ctx_id = session.pres_ctx_id;
				ses_rtse_reassemble = TRUE;
			}
		}
	}
	return offset;
}
Пример #20
0
static void
dissect_rmi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item *ti;
    proto_tree *rmi_tree;

    tvbuff_t   *next_tvb;

    gint       offset;
    gint       next_offset;
    int        datalen;

    guint16    version, len, port;
    guint8     message, proto;

    rmi_type   rmitype;

    const char *epid_hostname;
    guint epid_len;

    offset     = 0;
    rmitype    = 0;

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

    datalen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);

    rmitype = get_rmi_type(tvb, offset, datalen);

    if (check_col(pinfo->cinfo, COL_INFO)) {
	switch(rmitype) {
	case RMI_OUTPUTSTREAM:
	    version = tvb_get_ntohs(tvb,4);
	    col_add_fstr(pinfo->cinfo, COL_INFO,
			 "JRMI, Version: %d, ", version);

	    proto   = tvb_get_guint8(tvb, 6);
	    col_append_str(pinfo->cinfo, COL_INFO,
			   val_to_str(proto, rmi_protocol_str,
				      "Unknown protocol"));
	    break;
	case RMI_OUTPUTMESSAGE:
	    message = tvb_get_guint8(tvb,0);
	    col_set_str(pinfo->cinfo, COL_INFO,
			"JRMI, ");
	    col_append_str(pinfo->cinfo, COL_INFO,
			   val_to_str(message, rmi_output_message_str,
				      "Unknown message"));
	    break;
	case RMI_INPUTSTREAM:
	    message = tvb_get_guint8(tvb,0);
	    col_set_str(pinfo->cinfo, COL_INFO,
			"JRMI, ");
	    col_append_str(pinfo->cinfo, COL_INFO,
			   val_to_str(message, rmi_input_message_str,
				      "Unknown message"));
	    break;
	case SERIALIZATION_DATA:
	    version = tvb_get_ntohs(tvb,2);
	    col_add_fstr(pinfo->cinfo, COL_INFO,
			 "Serialization data, Version: %d", version);
	    break;
	default:
	    col_set_str(pinfo->cinfo, COL_INFO, "Continuation");
	    break;
	}
    }

    if (tree) {
	ti = proto_tree_add_item(tree, proto_rmi, tvb, 0, -1, ENC_NA);
	rmi_tree = proto_item_add_subtree(ti, ett_rmi);
	switch(rmitype) {
	case RMI_OUTPUTSTREAM:
	    /* XXX - uint, or string? */
	    proto_tree_add_uint(rmi_tree, hf_rmi_magic,
				tvb, offset,     4, tvb_get_ntohl(tvb,0));
	    proto_tree_add_item(rmi_tree, hf_rmi_version,
				tvb, offset + 4, 2, ENC_BIG_ENDIAN);
	    proto_tree_add_item(rmi_tree, hf_rmi_protocol,
				  tvb, offset + 6, 1, ENC_BIG_ENDIAN);
	    break;
	case RMI_INPUTSTREAM:
	    message = tvb_get_guint8(tvb, 0);
	    proto_tree_add_uint(rmi_tree, hf_rmi_inputmessage,
				  tvb, offset, 1, message);
	    if(message == RMI_INPUTSTREAM_MESSAGE_ACK) {
		proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
				    "EndPointIdentifier");
		/* MESSAGE_ACK should include EndpointIdentifier */
		len = tvb_get_ntohs(tvb, 1);
		proto_tree_add_uint(rmi_tree, hf_rmi_epid_length,
				       tvb, offset + 1, 2, len);
		epid_len = len < ITEM_LABEL_LENGTH ? len : ITEM_LABEL_LENGTH;
		if (epid_len > 0) {
			epid_hostname = tvb_format_text(tvb, offset + 3, epid_len);
		} else {
			epid_hostname = "[Empty]";
		}
		proto_tree_add_string(rmi_tree, hf_rmi_epid_hostname,
				      tvb, offset + 3, len, epid_hostname);

		port = tvb_get_ntohs(tvb, offset + len + 5);
  		proto_tree_add_uint(rmi_tree, hf_rmi_epid_port,
  				    tvb, offset + len + 5, 2, port);
	    }
	    if(message == RMI_INPUTSTREAM_MESSAGE_RETURNDATA) {
		proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
				    "Serialization Data");
		next_tvb = tvb_new_subset_remaining(tvb, offset + 1);
		dissect_ser(next_tvb, tree);
	    }
	    break;
	case RMI_OUTPUTMESSAGE:
	    message = tvb_get_guint8(tvb, 0);
	    proto_tree_add_uint(rmi_tree, hf_rmi_outputmessage,
				  tvb, offset, 1, message);
	    if(message == RMI_OUTPUTSTREAM_MESSAGE_CALL) {
		proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
				    "Serialization Data");
		/* XXX */
		next_tvb = tvb_new_subset_remaining(tvb, offset + 1);
		dissect_ser(next_tvb, tree);
	    }
	    if(message == RMI_OUTPUTSTREAM_MESSAGE_DGCACK) {
		proto_tree_add_text(rmi_tree, tvb, offset + 1, -1,
				    "UniqueIdentifier");
	    }
	    break;
	case SERIALIZATION_DATA:
	    dissect_ser(tvb, tree);
	    break;
	default:
	    break;
	}
    }
}
Пример #21
0
static void
dissect_icap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*icap_tree = NULL;
	proto_item	*ti = NULL;
	proto_item	*hidden_item;
	gint		offset = 0;
	const guchar	*line;
	gint		next_offset;
	const guchar	*linep, *lineend;
	int		linelen;
	guchar		c;
	icap_type_t     icap_type;
	int		datalen;

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

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

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

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

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

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

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

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

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

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

			switch (c) {

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

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

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

	if (tree) {
		switch (icap_type) {

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

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

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

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

		case ICAP_OTHER:
		default:
			break;
		}
	}

	datalen = tvb_length_remaining(tvb, offset);
	if (datalen > 0) {
		call_dissector(data_handle,
		    tvb_new_subset_remaining(tvb, offset), pinfo, icap_tree);
	}
}
Пример #22
0
static void
dissect_tzsp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree *tzsp_tree = NULL;
	proto_item *ti = NULL;
	int pos = 0;
	tvbuff_t *next_tvb;
	guint16 encapsulation = 0;
	int wtap_encap;
	dissector_handle_t encap_dissector;
	const char *encap_name;
	const char *info;
	guint8 type;

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

	type = tvb_get_guint8(tvb, 1);

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

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

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

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

	if (type != 4 && type != 5) {
		pos = add_option_info(tvb, 4, tzsp_tree, ti);

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

			col_set_str(pinfo->cinfo, COL_PROTOCOL, "UNKNOWN");
			if (check_col(pinfo->cinfo, COL_INFO))
				col_add_fstr(pinfo->cinfo, COL_INFO, "TZSP_ENCAP = %u",
				    encapsulation);
			call_dissector(data_handle, next_tvb, pinfo, tree);
		}
	}
}