Beispiel #1
0
/* Calculates a CRC32 checksum from the tvb zeroing out four bytes at the offset and checks it with the given crc32 and adds the result to the tree
 * Returns true if the calculated CRC32 matches the passed CRC32.
 * */
static gboolean ts2_add_checked_crc32(proto_tree *tree, int hf_item, tvbuff_t *tvb, guint16 offset, guint32 icrc32 )
{
    guint8  *zero;
    gint     len;
    guint32  ocrc32;

    zero = (guint8 *)wmem_alloc0(wmem_packet_scope(), 4);
    ocrc32 = crc32_ccitt_tvb(tvb, offset);
    ocrc32 = crc32_ccitt_seed(zero, 4, 0xffffffff-ocrc32);
    len = tvb_reported_length_remaining(tvb, offset+4);
    if (len<0)
        return FALSE;
    ocrc32 = crc32_ccitt_tvb_offset_seed(tvb, offset+4, (guint)len, 0xffffffff-ocrc32);
    if(icrc32==ocrc32)
    {
        proto_tree_add_uint_format(tree, hf_item, tvb, offset, 4, tvb_get_letohl(tvb, 16), "crc32: 0x%04x [correct]", tvb_get_letohl(tvb, offset));
        return TRUE;
    }
    else
    {
        proto_tree_add_uint_format(tree, hf_item, tvb, offset, 4, tvb_get_letohl(tvb,16), "crc32: 0x%04x [incorrect, should be 0x%04x]", tvb_get_letohl(tvb, offset),ocrc32);
        return FALSE;
    }
}
static void
dissect_tacplus_args_list( tvbuff_t *tvb, proto_tree *tree, int data_off, int len_off, int arg_cnt )
{
	int i;
	guint8	buff[257];
	for(i=0;i<arg_cnt;i++){
		int len=tvb_get_guint8(tvb,len_off+i);
		proto_tree_add_uint_format(tree, hf_tacplus_arg_length, tvb, len_off+i, 1, len,
									"Arg[%d] length: %d", i, len);
		tvb_get_nstringz0(tvb, data_off, len+1, buff);
		proto_tree_add_string_format(tree, hf_tacplus_arg_value, tvb, data_off, len, buff,
									"Arg[%d] value: %s", i, buff);
		data_off+=len;
	}
}
Beispiel #3
0
static void
dissect_status_type_identification_parameter(tvbuff_t *parameter_tvb, proto_tree *parameter_tree, proto_item *parameter_item)
{
  guint16 status_type, status_id;

  status_type = tvb_get_ntohs(parameter_tvb, STATUS_TYPE_OFFSET);
  status_id   = tvb_get_ntohs(parameter_tvb, STATUS_IDENT_OFFSET);

  proto_tree_add_item(parameter_tree, hf_status_type, parameter_tvb, STATUS_TYPE_OFFSET, STATUS_TYPE_LENGTH, NETWORK_BYTE_ORDER);
  proto_tree_add_uint_format(parameter_tree, hf_status_id,  parameter_tvb, STATUS_IDENT_OFFSET, STATUS_IDENT_LENGTH,
                             status_id, "Status identification: %u (%s)", status_id,
                             val_to_str(status_type * 256 * 256 + status_id, status_type_id_values, "unknown"));

  proto_item_append_text(parameter_item, " (%s)",
                         val_to_str(status_type * 256 * 256 + status_id, status_type_id_values, "unknown status information"));
}
static void
dissect_tacplus_args_list( tvbuff_t *tvb, proto_tree *tree, int data_off, int len_off, int arg_cnt )
{
	int i;
	int len;
	guint8 *value;
	for(i=0;i<arg_cnt;i++){
		len=tvb_get_guint8(tvb,len_off+i);
		proto_tree_add_uint_format(tree, hf_tacplus_arg_length, tvb, len_off+i, 1, len,
									"Arg[%d] length: %d", i, len);
		value=tvb_get_string_enc(wmem_packet_scope(), tvb, data_off, len, ENC_ASCII|ENC_NA);
		proto_tree_add_string_format(tree, hf_tacplus_arg_value, tvb, data_off, len, value,
									"Arg[%d] value: %s", i, value);
		data_off+=len;
	}
}
Beispiel #5
0
static void
decode_iei_ns_vci(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
  guint16 ns_vci;

  if (bi->nsip_tree) {
    ns_vci = tvb_get_ntohs(bi->tvb, bi->offset);

    proto_tree_add_uint_format(bi->nsip_tree, hf_nsip_ns_vci,
                               bi->tvb, ie_start_offset, ie->total_length,
                               ns_vci,
                               "NS VCI: %#04x", ns_vci);
    col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP,
        "NS VCI: %#04x", ns_vci);
    proto_item_append_text(bi->ti, ", NS VCI: %#04x", ns_vci);
  }
  bi->offset += ie->value_length;
}
Beispiel #6
0
static int
dissect_mip6_bu(tvbuff_t *tvb, proto_tree *mip6_tree, packet_info *pinfo)
{
	proto_tree *data_tree = NULL;
	proto_item *ti;
	int lifetime;

	col_set_str(pinfo->cinfo, COL_INFO, "Binding Update");

	if (mip6_tree) {
		ti = proto_tree_add_text(mip6_tree, tvb, MIP6_DATA_OFF, 
				MIP6_BU_LEN, "Binding Update");
		data_tree = proto_item_add_subtree(ti, ett_mip6);

		proto_tree_add_item(data_tree, hf_mip6_bu_seqnr, tvb,
				MIP6_BU_SEQNR_OFF, MIP6_BU_SEQNR_LEN, FALSE);

		proto_tree_add_item(data_tree, hf_mip6_bu_a_flag, tvb, 
				MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
		proto_tree_add_item(data_tree, hf_mip6_bu_h_flag, tvb, 
				MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
		proto_tree_add_item(data_tree, hf_mip6_bu_l_flag, tvb, 
				MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
		proto_tree_add_item(data_tree, hf_mip6_bu_k_flag, tvb, 
				MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
		proto_tree_add_item(data_tree, hf_mip6_bu_m_flag, tvb, 
				MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
		proto_tree_add_item(data_tree, hf_nemo_bu_r_flag, tvb, 
				MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);
		proto_tree_add_item(data_tree, hf_proxy_bu_p_flag, tvb, 
				MIP6_BU_FLAGS_OFF, MIP6_BU_FLAGS_LEN, FALSE);

		if ((tvb_get_guint8(tvb, MIP6_BU_FLAGS_OFF) & 0x0004 ) == 0x0004)
			proto_nemo = 1;

		lifetime = tvb_get_ntohs(tvb, MIP6_BU_LIFETIME_OFF);
		proto_tree_add_uint_format(data_tree, hf_mip6_bu_lifetime, tvb,
				MIP6_BU_LIFETIME_OFF, 
				MIP6_BU_LIFETIME_LEN, lifetime,
				"Lifetime: %d (%ld seconds)",
				lifetime, (long)lifetime * 4);
	}

	return MIP6_DATA_OFF + MIP6_BU_LEN;
}
Beispiel #7
0
static void
dissect_gdb_token(void *tvbparse_data, const void *wanted_data, tvbparse_elem_t *tok)
{
    proto_tree *tree;
    guint       token;
    guint8      ack;

    if (!tok)   /* XXX - is this check necessary? */
        return;

    tree = (proto_tree *)tvbparse_data;
    token = GPOINTER_TO_UINT(wanted_data);

    /* XXX - check that tok->len is what we expect? */
    switch (token) {
        case GDB_TOK_ACK:
            ack = tvb_get_guint8(tok->tvb, tok->offset);
            proto_tree_add_uint_format(tree, hf_gdb_ack,
                    tok->tvb, tok->offset, tok->len, ack,
                    "Acknowledgement: %s (%c)",
                    val_to_str_const(ack, gdb_ack, "unknown"), ack);
            break;
        case GDB_TOK_START:
            proto_tree_add_item(tree, hf_gdb_start,
                    tok->tvb, tok->offset, tok->len, ENC_ASCII|ENC_NA);
            break;
        case GDB_TOK_PAYLOAD:
            proto_tree_add_item(tree, hf_gdb_payload,
                    tok->tvb, tok->offset, tok->len, ENC_NA);
            break;
        case GDB_TOK_END:
            proto_tree_add_item(tree, hf_gdb_end,
                    tok->tvb, tok->offset, tok->len, ENC_ASCII|ENC_NA);
            break;
        case GDB_TOK_CHKSUM:
            /* the spec is not really explicit but it seems that the
               checksum is big endian */
            proto_tree_add_item(tree, hf_gdb_chksum,
                    tok->tvb, tok->offset, tok->len, ENC_BIG_ENDIAN);
            break;
        default:
            break;
    }
}
Beispiel #8
0
static void
dissect_whoent(tvbuff_t *tvb, int offset, proto_tree *tree)
{
	proto_tree	*whoent_tree = NULL;
	proto_item	*whoent_ti = NULL;
	int		line_offset = offset;
	guint8		*out_line;
	guint8		*out_name;
	nstime_t	ts;
	int		whoent_num = 0;
	guint32		idle_secs; /* say that out loud... */

	ts.nsecs = 0;

	while (tvb_reported_length_remaining(tvb, line_offset) > 0
	    && whoent_num < MAX_NUM_WHOENTS) {
		whoent_ti = proto_tree_add_item(tree, hf_who_whoent, tvb,
		    line_offset, SIZE_OF_WHOENT, ENC_NA);
		whoent_tree = proto_item_add_subtree(whoent_ti, ett_whoent);

		out_line = tvb_get_stringzpad(wmem_packet_scope(), tvb, line_offset, 8, ENC_ASCII|ENC_NA);
		proto_tree_add_string(whoent_tree, hf_who_tty, tvb, line_offset,
		    8, out_line);
		line_offset += 8;

		out_name = tvb_get_stringzpad(wmem_packet_scope(), tvb, line_offset, 8, ENC_ASCII|ENC_NA);
		proto_tree_add_string(whoent_tree, hf_who_uid, tvb, line_offset,
		    8, out_name);
		line_offset += 8;

		ts.secs = tvb_get_ntohl(tvb, line_offset);
		proto_tree_add_time(whoent_tree, hf_who_timeon, tvb,
		    line_offset, 4, &ts);
		line_offset += 4;

		idle_secs = tvb_get_ntohl(tvb, line_offset);
		proto_tree_add_uint_format(whoent_tree, hf_who_idle, tvb,
		    line_offset, 4, idle_secs, "Idle: %s",
		    time_secs_to_str(wmem_packet_scope(), idle_secs));
		line_offset += 4;

		whoent_num++;
	}
}
Beispiel #9
0
static void
dissect_whoent(tvbuff_t *tvb, int offset, proto_tree *tree)
{
	proto_tree	*whoent_tree = NULL;
	proto_item	*whoent_ti = NULL;
	int		line_offset = offset;
	gchar		out_line[9];
	gchar		out_name[9];
	nstime_t	ts;
	int		whoent_num = 0;
	guint32		idle_secs; /* say that out loud... */

	ts.nsecs = 0;

	while (tvb_reported_length_remaining(tvb, line_offset) > 0
	    && whoent_num < MAX_NUM_WHOENTS) {
		whoent_ti = proto_tree_add_item(tree, hf_who_whoent, tvb,
		    line_offset, SIZE_OF_WHOENT, FALSE);
		whoent_tree = proto_item_add_subtree(whoent_ti, ett_whoent);

	    	tvb_get_nstringz0(tvb, line_offset, sizeof(out_line), (guint8*)out_line);
		proto_tree_add_string(whoent_tree, hf_who_tty, tvb, line_offset,
		    8, out_line);
		line_offset += 8;

	    	tvb_get_nstringz0(tvb, line_offset, sizeof(out_name), (guint8*)out_name);
		proto_tree_add_string(whoent_tree, hf_who_uid, tvb, line_offset,
		    8, out_name);
		line_offset += 8;

		ts.secs = tvb_get_ntohl(tvb, line_offset);
		proto_tree_add_time(whoent_tree, hf_who_timeon, tvb,
		    line_offset, 4, &ts);
		line_offset += 4;

		idle_secs = tvb_get_ntohl(tvb, line_offset);
		proto_tree_add_uint_format(whoent_tree, hf_who_idle, tvb,
		    line_offset, 4, idle_secs, "Idle: %s",
		    time_secs_to_str(idle_secs));
		line_offset += 4;

		whoent_num++;
	}
}
static gint
dissect_tss_mo_state(tvbuff_t *tvb, gint offset, proto_tree *tree)
{
	guint8 tmp;
	guint  i = 0;

	for (i = 0; i < 8; i+= 2) {
		tmp = tvb_get_guint8(tvb, offset);
		proto_tree_add_uint_format(tree, hf_om2k_tsn_state, tvb, offset, 1, tmp & 0xf,
					   "Timslot %u MO State: %s", i,
					   val_to_str(tmp & 0xf, om2k_mo_state_vals, "unknown (%02d)"));
		proto_tree_add_uint_format(tree, hf_om2k_tsn_state, tvb, offset, 1, tmp >> 4,
					   "Timslot %u MO State: %s", i+1,
					   val_to_str(tmp >> 4, om2k_mo_state_vals, "unknown (%02d)"));
		offset++;
	}

	return 4;
}
Beispiel #11
0
static void
dissect_trmac(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*mac_tree = NULL;
	proto_item	*ti;
	int		mv_length, sv_offset, sv_additional;
	guint8		mv_val;

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

	mv_val = tvb_get_guint8(tvb, 3);

	/* Interpret the major vector */
	if (check_col(pinfo->cinfo, COL_INFO))
		col_add_str(pinfo->cinfo, COL_INFO,
		    val_to_str(mv_val, major_vector_vs, "Unknown Major Vector: %u"));

	if (tree) {
		mv_length = tvb_get_ntohs(tvb, 0);
		ti = proto_tree_add_item(tree, proto_trmac, tvb, 0, mv_length, FALSE);
		mac_tree = proto_item_add_subtree(ti, ett_tr_mac);

		proto_tree_add_uint(mac_tree, hf_trmac_mv, tvb, 3, 1, mv_val);
		proto_tree_add_uint_format(mac_tree, hf_trmac_length, tvb, 0, 2, mv_length,
				"Total Length: %d bytes", mv_length);
		proto_tree_add_uint(mac_tree, hf_trmac_srcclass, tvb, 2, 1, tvb_get_guint8(tvb, 2) & 0x0f);
		proto_tree_add_uint(mac_tree, hf_trmac_dstclass, tvb, 2, 1, tvb_get_guint8(tvb, 2) >> 4 );

		/* interpret the subvectors */
		sv_offset = 4;
		while (sv_offset < mv_length) {
			sv_additional = sv_text(tvb, sv_offset, mac_tree);

			/* if this is a bad packet, we could get a 0-length added here,
			 * looping forever */
			if (sv_additional > 0)
				sv_offset += sv_additional;
			else
				break;
		}
	}
}
/* add the list of fragments for this sdu to 'tree' */
static void tree_add_fragment_list_incomplete(struct rlc_sdu *sdu, tvbuff_t *tvb, proto_tree *tree)
{
	proto_item *ti;
	proto_tree *frag_tree;
	guint16 offset;
	struct rlc_frag *sdufrag;
	ti = proto_tree_add_item(tree, hf_rlc_frags, tvb, 0, 0, FALSE);
	frag_tree = proto_item_add_subtree(ti, ett_rlc_fragments);
	proto_item_append_text(ti, " (%u bytes, %u fragments): ",
		sdu->len, sdu->fragcnt);
	sdufrag = sdu->frags;
	offset = 0;
	while (sdufrag) {
		proto_tree_add_uint_format(frag_tree, hf_rlc_frag, tvb, 0,
			0, sdufrag->frame_num, "Frame: %u, payload %u-%u (%u bytes) (Seq: %u)",
			sdufrag->frame_num, offset, offset + sdufrag->len - 1, sdufrag->len, sdufrag->seq);
		offset += sdufrag->len;
		sdufrag = sdufrag->next;
	}
}
Beispiel #13
0
static void
dissect_response_pdu(tvbuff_t *tvb, proto_tree *tree, int offset, int len, guint8 flags)
{
	proto_tree* subtree;
	guint encoding = (flags & NETWORK_BYTE_ORDER) ? ENC_BIG_ENDIAN : ENC_LITTLE_ENDIAN;
	guint32 r_uptime;

	subtree = proto_tree_add_subtree(tree, tvb, offset, len, ett_response, NULL, "Response-PDU");

	NORLEL(flags, r_uptime, tvb, offset);
	proto_tree_add_uint_format(subtree, hf_resp_uptime, tvb, offset, 4, r_uptime,
			"sysUptime: %s", time_msecs_to_str(wmem_packet_scope(), r_uptime));
	proto_tree_add_item(subtree, hf_resp_error,  tvb, offset + 4, 2, encoding);
	proto_tree_add_item(subtree, hf_resp_index,  tvb, offset + 6, 2, encoding);
	offset += 8;

	len += PDU_HDR_LEN;
	while(len > offset) {
		offset += dissect_varbind(tvb, subtree, offset, len, flags);
	}
}
Beispiel #14
0
static void
decode_iei_cause(nsip_ie_t *ie, build_info_t *bi, int ie_start_offset) {
  guint8 cause;

  if (bi->nsip_tree) {
    cause = tvb_get_guint8(bi->tvb, bi->offset);
    proto_tree_add_uint_format(bi->nsip_tree, hf_nsip_cause,
                               bi->tvb, ie_start_offset, ie->total_length,
                               cause,
                               "Cause: %s (%#02x)",
                               val_to_str_const(cause, tab_nsip_cause_values,
                                                "Unknown"), cause);
    col_append_sep_fstr(bi->pinfo->cinfo, COL_INFO, NSIP_SEP,
        "Cause: %s",
        val_to_str(cause, tab_nsip_cause_values, "Unknown (0x%02x)"));

    proto_item_append_text(bi->ti, ", Cause: %s",
            val_to_str(cause, tab_nsip_cause_values, "Unknown (0x%02x)"));
  }
  bi->offset += ie->value_length;
}
/*
 * Dissect 802.11 with a variable-length link-layer header and a pseudo-
 * header containing radio information.
 */
static void
dissect_radio (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree)
{
  proto_item *ti = NULL;
  proto_tree *radio_tree = NULL;

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

  /* Add the radio information to the column information */
  col_add_fstr(pinfo->cinfo, COL_TX_RATE, "%u.%u",
        pinfo->pseudo_header->ieee_802_11.data_rate / 2,
        pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0);
    /* XX - this is a percentage, not a dBm or normalized or raw RSSI */
  col_add_fstr(pinfo->cinfo, COL_RSSI, "%u",
        pinfo->pseudo_header->ieee_802_11.signal_level);

  if (tree) {
    ti = proto_tree_add_item(tree, proto_radio, tvb, 0, 0, ENC_NA);
    radio_tree = proto_item_add_subtree (ti, ett_radio);

    proto_tree_add_uint64_format(radio_tree, hf_data_rate, tvb, 0, 0,
             (guint64)pinfo->pseudo_header->ieee_802_11.data_rate * 500000,
             "Data Rate: %u.%u Mb/s",
             pinfo->pseudo_header->ieee_802_11.data_rate / 2,
             pinfo->pseudo_header->ieee_802_11.data_rate & 1 ? 5 : 0);

    proto_tree_add_uint(radio_tree, hf_channel, tvb, 0, 0,
            pinfo->pseudo_header->ieee_802_11.channel);

    proto_tree_add_uint_format(radio_tree, hf_signal_strength, tvb, 0, 0,
            pinfo->pseudo_header->ieee_802_11.signal_level,
            "Signal Strength: %u%%",
            pinfo->pseudo_header->ieee_802_11.signal_level);
  }

  /* dissect the 802.11 header next */
  pinfo->current_proto = "IEEE 802.11";
  call_dissector(ieee80211_handle, tvb, pinfo, tree);
}
Beispiel #16
0
static void
dissect_netrom_type(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree,
			int hf_netrom_type_param, gint ett_netrom_type_param, const netrom_tf_items *type_items )
{
	proto_tree *tc;
	proto_tree *type_tree;
	char       *info_buffer;
	guint8      type;
	guint8      op_code;

	type    =  tvb_get_guint8( tvb, offset );
	op_code = type &0x0f;

	info_buffer = ep_strdup_printf( "%s%s%s%s (0x%02x)",
					val_to_str_const( op_code, op_code_vals_text, "Unknown" ),
					( type & NETROM_MORE_FLAG  ) ? ", More"  : "",
					( type & NETROM_NAK_FLAG   ) ? ", NAK"   : "",
					( type & NETROM_CHOKE_FLAG ) ? ", Choke" : "",
					type );
	col_add_str( pinfo->cinfo, COL_INFO, info_buffer );

	if ( tree )
		{
		tc = proto_tree_add_uint_format( tree,
						hf_netrom_type_param,
						tvb,
						offset,
						1,
						type,
						"Type field: %s",
						info_buffer
						);
		type_tree = proto_item_add_subtree( tc, ett_netrom_type_param );

		proto_tree_add_item( type_tree, *type_items->hf_tf_op, tvb, offset, 1, ENC_BIG_ENDIAN );
		proto_tree_add_item( type_tree, *type_items->hf_tf_choke, tvb, offset, 1, ENC_BIG_ENDIAN );
		proto_tree_add_item( type_tree, *type_items->hf_tf_nak, tvb, offset, 1, ENC_BIG_ENDIAN );
		proto_tree_add_item( type_tree, *type_items->hf_tf_more, tvb, offset, 1, ENC_BIG_ENDIAN );
		}
}
Beispiel #17
0
static guint parse_list(tvbuff_t *tvb, guint offset, proto_tree *tree,
        int hf_item, const char* msg, gboolean have_position)
{
    proto_item *fitem;
    proto_tree *ftree;
    guint32 arr_len, i, val, j;

    arr_len = tvb_get_ntohl(tvb, offset);
    fitem = proto_tree_add_uint_format(tree, hf_item, tvb, offset, 4, arr_len,
        "%s (count: %u)", msg, arr_len);
    offset += 4;

    ftree = proto_item_add_subtree(fitem, ett_rpcordma_chunk);

    for (i = 0; i < arr_len; ++i) {
        val = tvb_get_ntohl(tvb, offset);
        offset += 4;
        for (j = 0; j < val; ++j) {
            if (have_position) {
                proto_tree_add_item(ftree, hf_rpcordma_position, tvb,
                            offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
            }

            /* xdr_rdma_segment */
            proto_tree_add_item(ftree, hf_rpcordma_rdma_handle, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
            offset += 4;
            proto_tree_add_item(ftree, hf_rpcordma_rdma_length, tvb,
                        offset, 4, ENC_BIG_ENDIAN);
            offset += 4;
            proto_tree_add_item(ftree, hf_rpcordma_rdma_offset, tvb,
                        offset, 8, ENC_BIG_ENDIAN);
            offset += 8;
        }
    }

    return offset;
}
Beispiel #18
0
static void
rs09(tvbuff_t *tvb, proto_tree *tree)
{
	static const int *byte1[] = { &hf_ipmi_chs_09_rs_param_version, NULL };
	proto_item *ti;
	proto_tree *s_tree;
	tvbuff_t *sub;
	guint8 pno;
	const char *desc;

	pno = tvb_get_guint8(tvb, 1) & 0x7f;
	if (pno < array_length(boot_options)) {
		desc = boot_options[pno].name;
	} else if (pno >= 96 && pno <= 127) {
		desc = "OEM";
	} else {
		desc = "Reserved";
	}

	proto_tree_add_bitmask_text(tree, tvb, 0, 1, NULL, NULL,
			ett_ipmi_chs_09_rs_byte1, byte1, TRUE, 0);

	ti = proto_tree_add_text(tree, tvb, 1, 1,
			"Boot option parameter selector: %s (0x%02x)",
			desc, pno);
	s_tree = proto_item_add_subtree(ti, ett_ipmi_chs_09_rs_byte2);
	proto_tree_add_item(s_tree, hf_ipmi_chs_09_rs_valid, tvb, 1, 1, TRUE);
	proto_tree_add_uint_format(s_tree, hf_ipmi_chs_09_rs_param_select, tvb, 1, 1,
			pno, "%sBoot option parameter selector: %s (0x%02x)",
			ipmi_dcd8(pno, 0x7f), desc, pno);

	if (pno < array_length(boot_options)) {
		sub = tvb_new_subset(tvb, 2, tvb_length(tvb) - 2, tvb_length(tvb) - 2);
		boot_options[pno].intrp(sub, tree);
	} else {
		proto_tree_add_item(tree, hf_ipmi_chs_09_rs_param_data, tvb, 2,
				tvb_length(tvb) - 2, TRUE);
	}
}
Beispiel #19
0
/* Set System Boot Options
 */
static void
rq08(tvbuff_t *tvb, proto_tree *tree)
{
	proto_item *ti;
	proto_tree *s_tree;
	tvbuff_t *sub;
	guint8 pno;
	const char *desc;

	pno = tvb_get_guint8(tvb, 0) & 0x7f;
	if (pno < array_length(boot_options)) {
		desc = boot_options[pno].name;
	} else if (pno >= 96 && pno <= 127) {
		desc = "OEM";
	} else {
		desc = "Reserved";
	}

	ti = proto_tree_add_text(tree, tvb, 0, 1,
			"Boot option parameter selector: %s (0x%02x)",
			desc, pno);
	s_tree = proto_item_add_subtree(ti, ett_ipmi_chs_08_byte1);
	proto_tree_add_item(s_tree, hf_ipmi_chs_08_valid, tvb, 0, 1, TRUE);
	proto_tree_add_uint_format(s_tree, hf_ipmi_chs_08_selector, tvb, 0, 1,
			pno, "%sBoot option parameter selector: %s (0x%02x)",
			ipmi_dcd8(pno, 0x7f), desc, pno);

	/* Data is optional; no data means 'just set validity' */
	if (tvb_length(tvb) > 1) {
		if (pno < array_length(boot_options)) {
			sub = tvb_new_subset(tvb, 1, tvb_length(tvb) - 1, tvb_length(tvb) - 1);
			boot_options[pno].intrp(sub, tree);
		} else {
			proto_tree_add_none_format(tree, hf_ipmi_chs_08_data, tvb, 1,
					tvb_length(tvb) - 1, "Parameter data: %s", desc);
		}
	}
}
Beispiel #20
0
static void dissect_response_pdu(tvbuff_t *tvb, proto_tree *tree,int offset,int len, char flags)
{
	proto_item* item;
        proto_tree* subtree;
	gboolean little_endian = !(flags & NETWORK_BYTE_ORDER);
	guint32 r_uptime;

	item = proto_tree_add_text(tree, tvb, offset, len, "Response-PDU");
	subtree = proto_item_add_subtree(item, ett_response);

	r_uptime = little_endian ? \
	    tvb_get_letohl(tvb, offset) : tvb_get_ntohl(tvb, offset);

	proto_tree_add_uint_format(subtree, hf_resp_uptime, tvb, offset, 4, r_uptime,
			"sysUptime: %s", time_msecs_to_str(r_uptime));
	proto_tree_add_item(subtree, hf_resp_error,  tvb, offset + 4, 2, little_endian);
	proto_tree_add_item(subtree, hf_resp_index,  tvb, offset + 6, 2, little_endian);
	offset += 8;

	while(len > offset) {
		offset += dissect_varbind(tvb, subtree, offset, len, flags);
	}
}
Beispiel #21
0
void
netbios_add_name(const char* label, tvbuff_t *tvb, int offset, proto_tree *tree)

{/* add a name field display tree. Display the name and station type in sub-tree */

	proto_tree *field_tree;
	proto_item *tf;
	char        name_str[(NETBIOS_NAME_LEN - 1)*4 + 1];
	int         name_type;
	const char *name_type_str;

					/* decode the name field */
	name_type = get_netbios_name( tvb, offset, name_str, (NETBIOS_NAME_LEN - 1)*4 + 1);
	name_type_str = netbios_name_type_descr(name_type);
	tf = proto_tree_add_text( tree, tvb, offset, NETBIOS_NAME_LEN,
	    	"%s: %s<%02x> (%s)", label, name_str, name_type, name_type_str);

	field_tree = proto_item_add_subtree( tf, ett_netb_name);
	proto_tree_add_string_format( field_tree, hf_netb_nb_name, tvb, offset,
		15, name_str, "%s", name_str);
	proto_tree_add_uint_format( field_tree, hf_netb_nb_name_type, tvb, offset + 15, 1, name_type,
		"0x%02x (%s)", name_type, name_type_str);
}
Beispiel #22
0
static void
dissect_nsip(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
  guint8 pdu_type;
  build_info_t bi = { NULL, 0, NULL, NULL, NULL, NULL };
  proto_tree *nsip_tree;

  bi.tvb = tvb;
  bi.pinfo = pinfo;
  bi.parent_tree = tree;

  pinfo->current_proto = "GPRS-NS";

  col_set_str(pinfo->cinfo, COL_PROTOCOL, "GPRS-NS");

  col_clear(pinfo->cinfo, COL_INFO);

  pdu_type = tvb_get_guint8(tvb, 0);
  bi.offset++;

  if (tree) {
    bi.ti = proto_tree_add_item(tree, proto_nsip, tvb, 0, -1,
                             ENC_NA);
    nsip_tree = proto_item_add_subtree(bi.ti, ett_nsip);
    proto_tree_add_uint_format(nsip_tree, hf_nsip_pdu_type, tvb, 0, 1,
                               pdu_type,
                               "PDU type: %s (%#02x)",
                               val_to_str_const(pdu_type, tab_nsip_pdu_types,
                                                "Unknown"), pdu_type);
    proto_item_append_text(bi.ti, ", PDU type: %s",
                               val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown"));
    bi.nsip_tree = nsip_tree;
  }

  col_add_str(pinfo->cinfo, COL_INFO,
              val_to_str_const(pdu_type, tab_nsip_pdu_types, "Unknown PDU type"));
  decode_pdu(pdu_type, &bi);
}
Beispiel #23
0
static int
display_LMNT_token(tvbuff_t *tvb, int offset, proto_tree *tree)
{
	guint16 Token;

	Token = tvb_get_letohs(tvb, offset);

	if (Token == 0xffff) {
		proto_tree_add_uint_format_value(tree, hf_lmnt_token, tvb, offset, 2,
			Token,
			"0x%04x (Windows NT Networking)", Token);
	} else {
		/*
		 * XXX - what is it if it's not 0xffff?
		 */
		proto_tree_add_uint_format(tree, hf_lm_token, tvb, offset, 2,
			Token,
			"LMNT Token: 0x%04x (Unknown)", Token);
	}

	offset += 2;

	return offset;
}
Beispiel #24
0
static void
dissect_time(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree    *time_tree;
    proto_item    *ti;

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

    col_add_fstr(pinfo->cinfo, COL_INFO, "TIME %s",
            pinfo->srcport == pinfo->match_uint ? "Response":"Request");

    ti = proto_tree_add_item(tree, proto_time, tvb, 0, -1, ENC_NA);
    time_tree = proto_item_add_subtree(ti, ett_time);

    proto_tree_add_text(time_tree, tvb, 0, 0,
            pinfo->srcport==pinfo->match_uint ? "Type: Response":"Type: Request");
    if (pinfo->srcport == pinfo->match_uint) {
        /* seconds since 1900-01-01 00:00:00 GMT, *not* 1970 */
        guint32 delta_seconds = tvb_get_ntohl(tvb, 0);
        proto_tree_add_uint_format(time_tree, hf_time_time, tvb, 0, 4,
                delta_seconds, "%s",
                abs_time_secs_to_ep_str(delta_seconds-2208988800U, time_display_type, TRUE));
    }
}
static void
dissect_DataStatus(tvbuff_t *tvb, int offset, proto_tree *tree, guint8 u8DataStatus)
{
    proto_item *sub_item;
    proto_tree *sub_tree;

    sub_item = proto_tree_add_uint_format(tree, hf_pn_rt_data_status, 
	    tvb, offset, 1, u8DataStatus,
	    "DataStatus: 0x%02x (Frame: %s and %s, Provider: %s and %s)", 
	    u8DataStatus, 
	    (u8DataStatus & 0x04) ? "Valid" : "Invalid",
	    (u8DataStatus & 0x01) ? "Primary" : "Backup",
	    (u8DataStatus & 0x20) ? "Ok" : "Problem",
	    (u8DataStatus & 0x10) ? "Run" : "Stop");
    sub_tree = proto_item_add_subtree(sub_item, ett_pn_rt_data_status);
    proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_ignore, tvb, offset, 1, u8DataStatus);
    proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_subframe_sender_mode, tvb, offset, 1, u8DataStatus);
    proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_ok, tvb, offset, 1, u8DataStatus);
    proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_operate, tvb, offset, 1, u8DataStatus);
    proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_res3, tvb, offset, 1, u8DataStatus);
    proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_valid, tvb, offset, 1, u8DataStatus);
    proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_res1, tvb, offset, 1, u8DataStatus);
    proto_tree_add_uint(sub_tree, hf_pn_rt_data_status_primary, tvb, offset, 1, u8DataStatus);
}
Beispiel #26
0
static void dissect_cimd_dcs(tvbuff_t *tvb, proto_tree *tree, gint pindex, gint startOffset, gint endOffset)
{
  /* Set up structures needed to add the param subtree and manage it */
  proto_item *param_item;
  proto_tree *param_tree;
  gint        offset;
  guint       dcs;
  guint       dcs_cg;           /* coding group */
  guint       dcs_cf;           /* compressed flag */
  guint       dcs_mcm;          /* message class meaning flag */
  guint       dcs_chs;          /* character set */
  guint       dcs_mc;           /* message class */
  guint       dcs_is;           /* indication sense */
  guint       dcs_it;           /* indication type */

  gchar* bigbuf = (gchar*)ep_alloc(1024);

  param_item = proto_tree_add_text(tree, tvb,
    startOffset + 1, endOffset - (startOffset + 1),
    "%s", cimd_vals_PC[pindex].strptr
  );
  param_tree = proto_item_add_subtree(param_item, (*vals_hdr_PC[pindex].ett_p));
  proto_tree_add_string(param_tree, hf_cimd_pcode_indicator, tvb,
    startOffset + 1, CIMD_PC_LENGTH,
    tvb_format_text(tvb, startOffset + 1, CIMD_PC_LENGTH)
  );

  offset = startOffset + 1 + CIMD_PC_LENGTH + 1;
  dcs    = decimal_int_value(tvb, offset, endOffset - offset);
  proto_tree_add_uint(param_tree, (*vals_hdr_PC[pindex].hf_p), tvb, offset, endOffset - offset, dcs);

  dcs_cg = (dcs & 0xF0) >> 4;
  other_decode_bitfield_value(bigbuf, dcs, (dcs_cg <= 0x07 ? 0xC0 : 0xF0), 8);
  proto_tree_add_uint_format(param_tree, hf_cimd_dcs_coding_group_indicator, tvb, offset, 1,
    dcs_cg, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_coding_group_indicator)->name,
    val_to_str(dcs_cg, cimd_dcs_coding_groups, "Unknown (%d)"), dcs_cg
  );

  if (dcs_cg <= 0x07)
  {
    dcs_cf = (dcs & 0x20) >> 5;
    other_decode_bitfield_value(bigbuf, dcs, 0x20, 8);
    proto_tree_add_uint_format(param_tree, hf_cimd_dcs_compressed_indicator, tvb, offset, 1,
      dcs_cf, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_compressed_indicator)->name,
      val_to_str(dcs_cf, cimd_dcs_compressed, "Unknown (%d)"), dcs_cf
    );

    dcs_mcm = (dcs & 0x10) >> 4;
    other_decode_bitfield_value(bigbuf, dcs, 0x10, 8);
    proto_tree_add_uint_format(param_tree, hf_cimd_dcs_message_class_meaning_indicator, tvb, offset, 1,
      dcs_mcm, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_message_class_meaning_indicator)->name,
      val_to_str(dcs_mcm, cimd_dcs_message_class_meaning, "Unknown (%d)"), dcs_mcm
    );

    dcs_chs = (dcs & 0x0C) >> 2;
    other_decode_bitfield_value(bigbuf, dcs, 0x0C, 8);
    proto_tree_add_uint_format(param_tree, hf_cimd_dcs_character_set_indicator, tvb, offset, 1,
      dcs_chs, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_character_set_indicator)->name,
      val_to_str(dcs_chs, cimd_dcs_character_set, "Unknown (%d)"), dcs_chs
    );

    if (dcs_mcm)
    {
      dcs_mc = (dcs & 0x03);
      other_decode_bitfield_value(bigbuf, dcs, 0x03, 8);
      proto_tree_add_uint_format(param_tree, hf_cimd_dcs_message_class_indicator, tvb, offset, 1,
        dcs_mc, "%s = %s: %s (%d)", bigbuf, proto_registrar_get_nth(hf_cimd_dcs_message_class_indicator)->name,
        val_to_str(dcs_mc, cimd_dcs_message_class, "Unknown (%d)"), dcs_mc
      );
    }
  }
Beispiel #27
0
static void dissect_msdp_notification(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int *offset, guint16 tlv_len)
{
        guint8 error, error_sub;
        const value_string *vals;

        proto_tree_add_item(tree, hf_msdp_not_o, tvb, *offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(tree, hf_msdp_not_error, tvb, *offset, 1, ENC_BIG_ENDIAN);
        error = tvb_get_guint8(tvb, *offset);
        error &= 0x7F;             /* Error is 7-bit field. O-bit is bit 8 */
        *offset += 1;

        /* Depending on the Error Code, we collect the correct
         * value_strings for the Error subcode
         */
        switch (error) {
        case MESSAGE_HEADER_ERROR:
                vals = hdr_error_vals;
                break;
        case SA_REQUEST_ERROR:
                vals = sa_req_error_vals;
                break;
        case SA_MESSAGE_SA_RESPONSE_ERROR:
                vals = sa_msg_error_vals;
                break;
        case FSM_ERROR:
                vals = fsm_error_vals;
                break;
        case HOLD_TIMER_EXPIRED:
        case NOTIFICATION:
        case CEASE:
                vals = sa_unspec_error_vals;
                break;
        default:
                vals = sa_unspec_error_vals;
                break;
        }

        error_sub = tvb_get_guint8(tvb, *offset);
        proto_tree_add_uint_format(tree, hf_msdp_not_error_sub, tvb, *offset, 1,
                                   error_sub, "Error subcode: %s (%u)",
                                   val_to_str(error_sub, vals, "<Unknown Error subcode>"),
                                   error_sub);
        *offset += 1;

        /* Do switch again, this time to dissect the data portion
         * correctly. Ugly.
         */
        switch (error) {
                tvbuff_t *next_tvb;
        case SA_REQUEST_ERROR:
                add_notification_data_ipv4addr(tvb, tree, offset, "Group address");
                break;
        case SA_MESSAGE_SA_RESPONSE_ERROR:
                if (error_sub == 0) {
                        break;
                } else if (error_sub == 1) {
                        proto_tree_add_item(tree, hf_msdp_not_entry_count, tvb, *offset, 1, ENC_BIG_ENDIAN);
                        *offset += 1;
                        break;
                } else if (error_sub == 2) {
                        add_notification_data_ipv4addr(tvb, tree, offset, "RP address");
                        break;
                } else if (error_sub == 3 || error_sub == 8) {
                        add_notification_data_ipv4addr(tvb, tree, offset, "Group address");
                        break;
                } else if (error_sub == 4) {
                        add_notification_data_ipv4addr(tvb, tree, offset, "Source address");
                        break;
                } else if (error_sub == 5) {
                        proto_tree_add_item(tree, hf_msdp_not_sprefix_len, tvb, *offset, 1, ENC_BIG_ENDIAN);
                        *offset += 1;
                        break;
                } else if (error_sub == 6) {
                        /* No break, causes fall through to next label */
                } else if (error_sub == 7) {
                        proto_tree_add_text(tree, tvb, *offset, tlv_len - 5,
                                            "Packet with unknown encapsulation: %u bytes",
                                            tlv_len - 5);
                        *offset += tlv_len - 5;
                        break;
                } else {
                        proto_tree_add_text(tree, tvb, *offset, tlv_len - 5,
                                            "<Unknown data>: %u bytes",
                                            tlv_len -5);
                        *offset += tlv_len - 5;
                        break;
                }
                /* Fall through */
        case MESSAGE_HEADER_ERROR:
        case NOTIFICATION:
                /* Data contains the message that had an error. Even a
                 * broken Notification message causes a Notification
                 * message with Error Code set to Notification to be
                 * sent back.
                 */
                next_tvb = tvb_new_subset_remaining(tvb, *offset);
                dissect_msdp(next_tvb, pinfo, tree);
                break;
        case FSM_ERROR:
        case HOLD_TIMER_EXPIRED:
        case CEASE:
                /* Do nothing. These contain no data */
                break;
        default:
                if (tlv_len - 5 > 0)
                proto_tree_add_text(tree, tvb, *offset, tlv_len - 5,
                                    "<Unknown data>: %u bytes",
                                    tlv_len -5);
                *offset += tlv_len - 5;
                break;
        }

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

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

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

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

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

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

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

	switch(pgmhdr_type) {
	case PGM_SPM_PCKT:
	case PGM_NAK_PCKT:
	case PGM_NNAK_PCKT:
	case PGM_NCF_PCKT:
	case PGM_POLR_PCKT:
	case PGM_ACK_PCKT:
		if (check_col(pinfo->cinfo, COL_INFO)) {
			col_add_fstr(pinfo->cinfo, COL_INFO,
				"%-5s sqn 0x%x gsi %s", pktname, sqn, gsi);
		}
		break;
	case PGM_RDATA_PCKT:
	case PGM_ODATA_PCKT:
		if (check_col(pinfo->cinfo, COL_INFO)) {
			col_add_fstr(pinfo->cinfo, COL_INFO,
			    "%-5s sqn 0x%x gsi %s tsdulen %d", pktname, sqn, gsi,
			    pgmhdr_tsdulen);
		}
		isdata = TRUE;
		break;
	case PGM_POLL_PCKT: {
		guint16 poll_stype = tvb_get_ntohs(tvb, 22);
		pollstname = val_to_str(poll_stype, poll_subtype_vals, "Unknown (0x%02x)");

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

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

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

		pgm_tree = proto_item_add_subtree(ti, ett_pgm);

		cursor = ptvcursor_new(pgm_tree, tvb, 0);

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

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

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

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

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

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

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

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

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

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

			default:
				proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				return;
			}
			break;
		case PGM_RDATA_PCKT:
		case PGM_ODATA_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_data);
			ptvcursor_set_tree(cursor, type_tree);

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

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

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

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

			default:
				proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

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

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

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

			default:
				proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				return;
			}
			break;
		case PGM_POLL_PCKT:
			type_tree = proto_item_add_subtree(tf, ett_pgm_poll);
			ptvcursor_set_tree(cursor, type_tree);

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

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

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

			default:
				proto_tree_add_text(type_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

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

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

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

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

		if (isdata)
			decode_pgm_ports(tvb, ptvcursor_current_offset(cursor), pinfo, tree, pgmhdr_sport, pgmhdr_dport);
	}
}
Beispiel #29
0
static void
dissect_pgmopts(ptvcursor_t* cursor, const char *pktname)
{
	proto_item *tf;
	proto_tree *opts_tree = NULL;
	proto_tree *opt_tree = NULL;
	tvbuff_t *tvb = ptvcursor_tvbuff(cursor);

	gboolean theend = FALSE;

	guint16 opts_total_len;
	guint8 genopts_type;
	guint8 genopts_len;
	guint8 opts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));

	if (opts_type != PGM_OPT_LENGTH) {
		proto_tree_add_text(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), 1,
		    "%s Options - initial option is %s, should be %s",
		    pktname,
		    val_to_str(opts_type, opt_vals, "Unknown (0x%02x)"),
		    val_to_str(PGM_OPT_LENGTH, opt_vals, "Unknown (0x%02x)"));
		return;
	}

	opts_total_len = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor)+2);

	if (opts_total_len < 4) {
		proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor)+2, 2,
			"%s Options (Total Length %u - invalid, must be >= 4)",
			pktname, opts_total_len);
		return;
	}

	tf = proto_tree_add_text(ptvcursor_tree(cursor), tvb, ptvcursor_current_offset(cursor), opts_total_len,
		"%s Options (Total Length %d)", pktname, opts_total_len);
	opts_tree = proto_item_add_subtree(tf, ett_pgm_opts);
	ptvcursor_set_tree(cursor, opts_tree);
	ptvcursor_add(cursor, hf_pgm_opt_type, 1, ENC_BIG_ENDIAN);
	ptvcursor_add(cursor, hf_pgm_opt_len, 1, ENC_BIG_ENDIAN);
	ptvcursor_add(cursor, hf_pgm_opt_tlen, 2, ENC_BIG_ENDIAN);

	for (opts_total_len -= 4; !theend && opts_total_len != 0;){
		if (opts_total_len < 4) {
			proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), opts_total_len,
			    "Remaining total options length doesn't have enough for an options header");
			break;
		}

		genopts_type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
		genopts_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor)+1);

		if (genopts_type & PGM_OPT_END)  {
			genopts_type &= ~PGM_OPT_END;
			theend = TRUE;
		}
		if (genopts_len < 4) {
			proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len,
				"Option: %s, Length: %u (invalid, must be >= 4)",
				val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"),
				genopts_len);
			break;
		}
		if (opts_total_len < genopts_len) {
			proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len,
			    "Option: %s, Length: %u (> remaining total options length)",
			    val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"),
			    genopts_len);
			break;
		}
		tf = proto_tree_add_text(opts_tree, tvb, ptvcursor_current_offset(cursor), genopts_len,
			"Option: %s, Length: %u",
			val_to_str(genopts_type, opt_vals, "Unknown (0x%02x)"),
			genopts_len);

		switch(genopts_type) {
		case PGM_OPT_JOIN:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_join);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_JOIN_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_JOIN_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_join_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_join_minjoin, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_PARITY_PRM:{
			guint8 optdata_po;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_parityprm);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);


			if (genopts_len < PGM_OPT_PARITY_PRM_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, ptvcursor_tvbuff(cursor),
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PARITY_PRM_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			optdata_po = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
			proto_tree_add_uint_format(opt_tree, hf_pgm_opt_parity_prm_po, tvb,
				ptvcursor_current_offset(cursor), 1, optdata_po, "Parity Parameters: %s (0x%x)",
				paritystr(optdata_po), optdata_po);
			ptvcursor_advance(cursor, 1);

			ptvcursor_add(cursor, hf_pgm_opt_parity_prm_prmtgsz, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_PARITY_GRP:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_paritygrp);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_PARITY_GRP_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PARITY_GRP_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_parity_grp_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_parity_grp_prmgrp, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_NAK_LIST:{
			guint8 optdata_len;
			guint32 naklist[PGM_MAX_NAK_LIST_SZ+1];
			unsigned char *nakbuf;
			gboolean firsttime;
			int i, j, naks, soffset;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_naklist);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			optdata_len = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_res, 1, ENC_BIG_ENDIAN);

			optdata_len -= PGM_OPT_NAK_LIST_SIZE;
			tvb_memcpy(tvb, (guint8 *)naklist, ptvcursor_current_offset(cursor), optdata_len);
			firsttime = TRUE;
			soffset = 0;
			naks = (optdata_len/sizeof(guint32));
			nakbuf = ep_alloc(8192);
			j = 0;
			/*
			 * Print out 8 per line
			 */
			for (i=0; i < naks; i++) {
				soffset += MIN(8192-soffset,
					g_snprintf(nakbuf+soffset, 8192-soffset, "0x%lx ",
						(unsigned long)g_ntohl(naklist[i])));
				if ((++j % 8) == 0) {
					if (firsttime) {
						proto_tree_add_bytes_format(opt_tree,
							hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
							nakbuf, "List(%d): %s", naks, nakbuf);
						soffset = 0;
						firsttime = FALSE;
					} else {
						proto_tree_add_bytes_format(opt_tree,
							hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
							nakbuf, "List: %s", nakbuf);
						soffset = 0;
					}
					ptvcursor_advance(cursor, j*4);
					j = 0;
				}
			}
			if (j) {
				if (firsttime) {
					proto_tree_add_bytes_format(opt_tree,
						hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
						nakbuf, "List(%d): %s", naks, nakbuf);
				} else {
					proto_tree_add_bytes_format(opt_tree,
						hf_pgm_opt_nak_list, tvb, ptvcursor_current_offset(cursor), j*4,
						nakbuf, "List: %s", nakbuf);
				}
				ptvcursor_advance(cursor, j*4);
			}
			break;
		}
		case PGM_OPT_PGMCC_DATA:{
			guint16 optdata_afi;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_ccdata);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_PGMCC_DATA_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PGMCC_DATA_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_tsp, 4, ENC_BIG_ENDIAN);
			optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_afi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccdata_res2, 2, ENC_BIG_ENDIAN);

			switch (optdata_afi) {

			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_opt_ccdata_acker, 4, ENC_BIG_ENDIAN);
				break;

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

			default:
				proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

			break;
		}
		case PGM_OPT_PGMCC_FEEDBACK:{
			guint16 optdata_afi;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_ccdata);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_PGMCC_FEEDBACK_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_PGMCC_FEEDBACK_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_tsp, 4, ENC_BIG_ENDIAN);
			optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_afi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_lossrate, 2, ENC_BIG_ENDIAN);

			switch (optdata_afi) {

			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_opt_ccfeedbk_acker, 4, ENC_BIG_ENDIAN);
				break;

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

			default:
				proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

			break;
		}
		case PGM_OPT_NAK_BO_IVL:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_nak_bo_ivl);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_NAK_BO_IVL_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_NAK_BO_IVL_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_ivl_bo_ivl_sqn, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_NAK_BO_RNG:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_nak_bo_rng);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_NAK_BO_RNG_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_NAK_BO_RNG_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_min_bo_ivl, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_nak_bo_rng_max_bo_ivl, 4, ENC_BIG_ENDIAN);

			break;
		}
		case PGM_OPT_REDIRECT:{
			guint16 optdata_afi;

			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_redirect);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_REDIRECT_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_REDIRECT_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_redirect_res, 1, ENC_BIG_ENDIAN);
			optdata_afi = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
			ptvcursor_add(cursor, hf_pgm_opt_redirect_afi, 2, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_redirect_res2, 2, ENC_BIG_ENDIAN);

			switch (optdata_afi) {

			case AFNUM_INET:
				ptvcursor_add(cursor, hf_pgm_opt_redirect_dlr, 4, ENC_BIG_ENDIAN);
				break;

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

			default:
				proto_tree_add_text(opt_tree, tvb, ptvcursor_current_offset(cursor), -1,
				    "Can't handle this address format");
				break;
			}

			break;
		}
		case PGM_OPT_FRAGMENT:{
			opt_tree = proto_item_add_subtree(tf, ett_pgm_opts_fragment);
			ptvcursor_set_tree(cursor, opt_tree);

			ptvcursor_add_no_advance(cursor, hf_pgm_genopt_end, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_type, 1, ENC_BIG_ENDIAN);

			if (genopts_len < PGM_OPT_FRAGMENT_SIZE) {
				proto_tree_add_uint_format(opt_tree, hf_pgm_genopt_len, tvb,
					ptvcursor_current_offset(cursor), 1, genopts_len,
					"Length: %u (bogus, must be >= %u)",
					genopts_len, PGM_OPT_FRAGMENT_SIZE);
				break;
			}
			ptvcursor_add(cursor, hf_pgm_genopt_len, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_genopt_opx, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_res, 1, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_first_sqn, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_offset, 4, ENC_BIG_ENDIAN);
			ptvcursor_add(cursor, hf_pgm_opt_fragment_total_length, 4, ENC_BIG_ENDIAN);

			break;
		}
		default:{
			ptvcursor_advance(cursor, genopts_len);
			break;
		}
		}

		opts_total_len -= genopts_len;
	}
	return;
}
Beispiel #30
0
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);
}