Exemplo n.º 1
0
static int get_address_v5(tvbuff_t *tvb, int offset,
    socks_hash_entry_t *hash_info) {

    /* decode the v5 address and return offset of next byte */
    int     a_type;
    address addr;

    a_type = tvb_get_guint8(tvb, offset);
    offset += 1;

    switch(a_type)
    {
    case 1: /* IPv4 address */
        if ( hash_info) {
            TVB_SET_ADDRESS(&addr, AT_IPv4, tvb, offset, 4);
            SE_COPY_ADDRESS(&hash_info->dst_addr, &addr);
        }
        offset += 4;
        break;

    case 4: /* IPv6 address */
        if ( hash_info) {
            TVB_SET_ADDRESS(&addr, AT_IPv6, tvb, offset, 16);
            SE_COPY_ADDRESS(&hash_info->dst_addr, &addr);
        }
        offset += 16;
        break;

    case 3: /* domain name address */
        offset += tvb_get_guint8(tvb, offset) + 1;
        break;
    }

    return offset;
}
Exemplo n.º 2
0
static void
dissect_arcnet_common (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree,
                       gboolean has_offset, gboolean has_exception)
{
  int offset = 0;
  guint8 dst, src, protID, split_flag;
  tvbuff_t *next_tvb;
  proto_item *ti = NULL;
  proto_tree *arcnet_tree = NULL;

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

  col_set_str(pinfo->cinfo, COL_INFO, "ARCNET");

  src = tvb_get_guint8 (tvb, 0);
  dst = tvb_get_guint8 (tvb, 1);
  TVB_SET_ADDRESS(&pinfo->dl_src,   AT_ARCNET, tvb, 0, 1);
  TVB_SET_ADDRESS(&pinfo->src,      AT_ARCNET, tvb, 0, 1);
  TVB_SET_ADDRESS(&pinfo->dl_dst,   AT_ARCNET, tvb, 1, 1);
  TVB_SET_ADDRESS(&pinfo->dst,      AT_ARCNET, tvb, 1, 1);

  ti = proto_tree_add_item (tree, proto_arcnet, tvb, 0, -1, ENC_NA);

  arcnet_tree = proto_item_add_subtree (ti, ett_arcnet);

  proto_tree_add_uint (arcnet_tree, hf_arcnet_src, tvb, offset, 1, src);
  offset++;

  proto_tree_add_uint (arcnet_tree, hf_arcnet_dst, tvb, offset, 1, dst);
  offset++;

  if (has_offset) {
    proto_tree_add_item (arcnet_tree, hf_arcnet_offset, tvb, offset, 2, ENC_NA);
    offset += 2;
  }

  protID = tvb_get_guint8 (tvb, offset);
  proto_tree_add_uint (arcnet_tree, hf_arcnet_protID, tvb, offset, 1, protID);
  offset++;

  switch (protID) {

  case ARCNET_PROTO_IP_1051:
  case ARCNET_PROTO_ARP_1051:
  case ARCNET_PROTO_DIAGNOSE:
  case ARCNET_PROTO_BACNET:     /* XXX - no fragmentation? */
    /* No fragmentation stuff in the header */
    break;

  default:
    /*
     * Show the fragmentation stuff - flag and sequence ID.
     *
     * XXX - on at least some versions of NetBSD, it appears that
     * we might get ARCNET frames, not reassembled packets; if so,
     * we should reassemble them.
     *
     * XXX - but on FreeBSD it appears that we get reassembled packets
     * on input (but apparently we get frames on output - or maybe
     * we get the packet *and* all its frames!); how to tell the
     * difference?  It looks from the FreeBSD reassembly code as if
     * the reassembled packet arrives with the header for the first
     * frame.  It also looks as if, on output, we first get the
     * full packet, with a header containing none of the fragmentation
     * stuff, and then get the frames.
     *
     * On Linux, we get only reassembled packets, and the exception
     * frame stuff is hidden - there's a split flag and sequence
     * number, but it appears that it will never have the exception
     * frame stuff.
     *
     * XXX - what about OpenBSD?  And, for that matter, what about
     * Windows?  (I suspect Windows supplies reassembled frames,
     * as WinPcap, like PF_PACKET sockets, taps into the networking
     * stack just as other protocols do.)
     */
    split_flag = tvb_get_guint8 (tvb, offset);
    if (has_exception && split_flag == 0xff) {
      /* This is an exception packet.  The flag value there is the
         "this is an exception flag" packet; the next two bytes
         after it are padding. */
      proto_tree_add_uint (arcnet_tree, hf_arcnet_exception_flag, tvb, offset, 1,
                           split_flag);
      offset++;

      proto_tree_add_item(arcnet_tree, hf_arcnet_padding, tvb, offset, 2, ENC_BIG_ENDIAN);
      offset += 2;

      /* Another copy of the packet type appears after the padding. */
      proto_tree_add_item (arcnet_tree, hf_arcnet_protID, tvb, offset, 1, ENC_BIG_ENDIAN);
      offset++;

      /* And after that comes the real split flag. */
      split_flag = tvb_get_guint8 (tvb, offset);
    }

    proto_tree_add_uint (arcnet_tree, hf_arcnet_split_flag, tvb, offset, 1,
                         split_flag);
    offset++;

    proto_tree_add_item (arcnet_tree, hf_arcnet_sequence, tvb, offset, 2, ENC_BIG_ENDIAN);
    offset += 2;

    break;
  }

  /* Set the length of the ARCNET header protocol tree item. */
  proto_item_set_len(ti, offset);

  next_tvb = tvb_new_subset_remaining (tvb, offset);

  if (!dissector_try_uint (arcnet_dissector_table, protID,
                           next_tvb, pinfo, tree))
    {
      col_add_fstr (pinfo->cinfo, COL_PROTOCOL, "0x%04x", protID);
      call_dissector (data_handle, next_tvb, pinfo, tree);
    }

}
Exemplo n.º 3
0
static int
dissect_ppcap_destination_address(tvbuff_t *tvb, packet_info * pinfo, proto_tree * ppcap_tree1, int offset)
{
	int key2;
	guint16 msg_len;
	msg_len = tvb_get_ntohs(tvb, offset);
	proto_tree_add_item( ppcap_tree1, hf_ppcap_length, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset  = offset + 2;
	proto_tree_add_item(ppcap_tree1, hf_ppcap_destreserved, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;

	key2 = tvb_get_ntohs(tvb, offset);
	proto_tree_add_item(ppcap_tree1, hf_ppcap_address_type, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;

	if (key2 == 1)
	{
		ssn = tvb_get_guint8(tvb, offset);
		proto_tree_add_item(ppcap_tree1, hf_ppcap_ssn1, tvb, offset, 1, ENC_BIG_ENDIAN);
		offset += 1;

		proto_tree_add_item(ppcap_tree1, hf_ppcap_spc1, tvb, offset, 3, ENC_BIG_ENDIAN);

		/*dst_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/
		mtp3_addr_dpc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t);
		mtp3_addr_dpc->pc = (guint32)tvb_get_ntoh24(tvb, offset);
		mtp3_addr_dpc->type = ITU_STANDARD;
		mtp3_addr_dpc->ni = 0;
		SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc);

		if (msg_len%4)
			msg_len = msg_len + (4 - (msg_len%4));

		offset += msg_len-1;
		return offset;

	}
	else if (key2 == 2)
	{
		proto_tree_add_item(ppcap_tree1, hf_ppcap_dpc, tvb, offset, 4, ENC_BIG_ENDIAN);

		/*dst_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/
		mtp3_addr_dpc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t);
		mtp3_addr_dpc->pc = tvb_get_ntohl(tvb, offset);
		mtp3_addr_dpc->type = ITU_STANDARD;
		mtp3_addr_dpc->ni = 0;
		SET_ADDRESS(&pinfo->dst, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_dpc);
	}
	else if (key2 == 3)
	{
		if (msg_len%16 != 0)
		{
			proto_tree_add_ipv4(ppcap_tree1, hf_ppcap_destination_ip_address1, tvb, offset, msg_len, tvb_get_ipv4(tvb, offset));
			TVB_SET_ADDRESS(&pinfo->net_dst, AT_IPv4, tvb, offset, 4);
			COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst);
		}
		else
		{
			struct e_in6_addr value;

			tvb_get_ipv6(tvb, offset,&value);
			proto_tree_add_ipv6(ppcap_tree1, hf_ppcap_destination_ip_address2, tvb, offset, msg_len, &value);
			TVB_SET_ADDRESS(&pinfo->net_dst, AT_IPv6, tvb, offset, 6);
			COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst);
		}
	}

	else if (key2 == 4)
	{
		char *string;
		string = tvb_get_string_enc(wmem_packet_scope(), tvb, offset, msg_len, ENC_UTF_8|ENC_NA);
		proto_tree_add_string(ppcap_tree1, hf_ppcap_destination_nodeid, tvb, offset, msg_len, string);
		TVB_SET_ADDRESS(&pinfo->net_dst, AT_STRINGZ, tvb, offset, msg_len);
		COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst);
	}

	if (msg_len%4)
		msg_len = msg_len+(4-(msg_len%4));

	offset += msg_len;

	return offset;
}
Exemplo n.º 4
0
static int
dissect_ppcap_source_address(tvbuff_t *tvb, packet_info *pinfo, proto_tree * ppcap_tree1, int offset)
{
	int key1;
	guint16 msg_len;
	msg_len = tvb_get_ntohs(tvb, offset);
	proto_tree_add_item( ppcap_tree1, hf_ppcap_length, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset  = offset + 2;
	proto_tree_add_item(ppcap_tree1, hf_ppcap_reserved, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;

	key1 = tvb_get_ntohs(tvb, offset);
	proto_tree_add_item(ppcap_tree1, hf_ppcap_address_type, tvb, offset, 2, ENC_BIG_ENDIAN);
	offset += 2;

	if (key1 == 1)
	{
		proto_tree_add_item(ppcap_tree1, hf_ppcap_ssn, tvb, offset, 1, ENC_BIG_ENDIAN);
		offset += 1;
		proto_tree_add_item(ppcap_tree1, hf_ppcap_spc, tvb, offset, 3, ENC_BIG_ENDIAN);
		/*src_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/
		mtp3_addr_opc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t);
		mtp3_addr_opc->pc = (guint32 )tvb_get_ntoh24(tvb, offset);
		mtp3_addr_opc->type = ITU_STANDARD;
		mtp3_addr_opc->ni = 0;
		/*SET_ADDRESS(&pinfo->net_src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc);*/
		SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc);
		if (msg_len%4)
			msg_len = msg_len + (4 - (msg_len%4));

		offset += msg_len-1;
		return offset;
	}
	else if (key1 == 2)
	{
		proto_tree_add_item(ppcap_tree1, hf_ppcap_opc, tvb, offset, msg_len, ENC_BIG_ENDIAN);

		/*src_addr1 = (guint32 )tvb_get_ntoh24(tvb, offset);*/
		mtp3_addr_opc = wmem_new0(wmem_packet_scope(), mtp3_addr_pc_t);
		mtp3_addr_opc->pc = tvb_get_ntohl(tvb, offset);
		mtp3_addr_opc->type = ITU_STANDARD;
		mtp3_addr_opc->ni = 0;
		SET_ADDRESS(&pinfo->src, AT_SS7PC, sizeof(mtp3_addr_pc_t), (guint8 *) mtp3_addr_opc);
	}
	else if (key1 == 3)
	{
		if (msg_len%16 != 0)
		{

			proto_tree_add_ipv4(ppcap_tree1, hf_ppcap_source_ip_address1, tvb, offset, msg_len, tvb_get_ipv4(tvb, offset));
			TVB_SET_ADDRESS(&pinfo->net_src, AT_IPv4, tvb, offset, 4);
			COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src);
		}
		else
		{
			struct e_in6_addr value;
			tvb_get_ipv6(tvb, offset, &value);
			proto_tree_add_ipv6(ppcap_tree1, hf_ppcap_source_ip_address2, tvb, offset, msg_len, &value);
			TVB_SET_ADDRESS(&pinfo->net_src, AT_IPv6, tvb, offset, 6);
			COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src);
		}
	}

	else if (key1 == 4)

	{
		proto_tree_add_item(ppcap_tree1, hf_ppcap_source_nodeid, tvb, offset, msg_len, ENC_ASCII|ENC_NA);
		TVB_SET_ADDRESS(&pinfo->net_src, AT_STRINGZ, tvb, offset, msg_len);
		COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src);
	}
	if (msg_len%4)
		msg_len = msg_len + (4 - (msg_len%4));
	offset += msg_len;
	return offset;
}
Exemplo n.º 5
0
static void
dissect_tr(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*tr_tree, *bf_tree;
	proto_item	*ti, *hidden_item;
	guint8		 rcf1, rcf2;
	tvbuff_t	*next_tvb;

	volatile int		frame_type;
	volatile int		fixoffset = 0;
	volatile int		source_routed = 0;
	volatile guint8		trn_rif_bytes;
	volatile guint8		actual_rif_bytes;
	volatile guint8		c1_nonsr;
	volatile guint8		c2_nonsr;
	volatile guint16	first2_sr;
	tvbuff_t		*volatile tr_tvb;

	static tr_hdr trh_arr[4];
	static int trh_current=0;
	tr_hdr *volatile trh;

	/* non-source-routed version of source addr */
	static guint8		trn_shost_nonsr[6]; /* has to be static due to SET_ADDRESS */
	int			x;

	/* Token-Ring Strings */
	static const char *fc[] = { "MAC", "LLC", "Reserved", "Unknown" };


	trh_current++;
	if(trh_current==4){
		trh_current=0;
	}
	trh=&trh_arr[trh_current];

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

	if (fix_linux_botches)
		x = check_for_old_linux_tvb((tvbuff_t*) tvb);
	else
		x = 0;
	if (x != 0) {
		/* Actually packet starts x bytes into what we have got but with all
		   source routing compressed. See comment above */
		tr_tvb = tvb_new_subset_remaining((tvbuff_t*) tvb, x);
	}
	else {
		tr_tvb = tvb;
	}

	/* Get the data */
	trh->fc		= tvb_get_guint8(tr_tvb, 1);
	TVB_SET_ADDRESS(&trh->src, AT_ETHER, tr_tvb, 8, 6);
	TVB_SET_ADDRESS(&trh->dst, AT_ETHER, tr_tvb, 2, 6);

	/* if the high bit on the first byte of src hwaddr is 1, then
		this packet is source-routed */
	memcpy(trn_shost_nonsr, trh->src.data, 6);
	source_routed = trn_shost_nonsr[0] & 128;
	trn_shost_nonsr[0] &= 127;

	frame_type = (trh->fc & 192) >> 6;

	col_add_fstr(pinfo->cinfo, COL_INFO, "Token-Ring %s", fc[frame_type]);

	trn_rif_bytes = tvb_get_guint8(tr_tvb, 14) & 31;

	if (fix_linux_botches) {
		/* the Linux 2.0 TR code strips source-route bits in
		 * order to test for SR. This can be removed from most
		 * packets with oltr, but not all. So, I try to figure out
		 * which packets should have been SR here. I'll check to
		 * see if there's a SNAP or IPX field right after
		 * my RIF fields.
		 *
		 * The Linux 2.4.18 code, at least appears to do the
		 * same thing, from a capture I got from somebody running
		 * 2.4.18 (RH 7.1, so perhaps this is a Red Hat
		 * "improvement").
		 */
		if (frame_type == 1 && !source_routed && trn_rif_bytes > 0) {
			TRY {

				c1_nonsr = tvb_get_guint8(tr_tvb, 14);
				c2_nonsr = tvb_get_guint8(tr_tvb, 15);

				if (c1_nonsr != c2_nonsr) {

					first2_sr = tvb_get_ntohs(tr_tvb, trn_rif_bytes + 0x0e);

					if ( ( first2_sr == 0xaaaa &&
						tvb_get_guint8(tr_tvb, trn_rif_bytes + 0x10) == 0x03)   ||

						first2_sr == 0xe0e0 ||
						first2_sr == 0xe0aa ) {

						source_routed = 1;
					}
				}
			}
			CATCH(BoundsError) {
				/* We had no information beyond the TR header. Just assume
				 * this is a normal (non-Linux) TR header. */
				;
			}
			ENDTRY;
		}
	}
Exemplo n.º 6
0
static void
dissect_netrom_proto(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item   *ti;
	proto_tree   *netrom_tree;
	int           offset;
#if 0
	guint8        src_ssid;
	guint8        dst_ssid;
#endif
	guint8        op_code;
	guint8        cct_index;
	guint8        cct_id;
	tvbuff_t     *next_tvb;

	col_set_str( pinfo->cinfo, COL_PROTOCOL, "NET/ROM" );
	col_clear( pinfo->cinfo, COL_INFO );

	offset = 0;

	/* source */
	TVB_SET_ADDRESS(&pinfo->dl_src,	AT_AX25, tvb, offset, AX25_ADDR_LEN);
	TVB_SET_ADDRESS(&pinfo->src,	AT_AX25, tvb, offset, AX25_ADDR_LEN);
	/* src_ssid = tvb_get_guint8(tvb, offset+6); */
	offset += AX25_ADDR_LEN; /* step over src addr */

	/* destination */
	TVB_SET_ADDRESS(&pinfo->dl_dst,	AT_AX25, tvb, offset, AX25_ADDR_LEN);
	TVB_SET_ADDRESS(&pinfo->dst,	AT_AX25, tvb, offset, AX25_ADDR_LEN);
	/* dst_ssid = tvb_get_guint8(tvb, offset+6); */
	offset += AX25_ADDR_LEN; /* step over dst addr */

	offset += 1; /* step over ttl */
	cct_index =  tvb_get_guint8( tvb, offset );
	offset += 1; /* step over cct index*/
	cct_id =  tvb_get_guint8( tvb, offset );
	offset += 1; /* step over cct id */
	offset += 1; /* step over n_s */
	offset += 1; /* step over n_r */

	/* frame type */
	op_code =  tvb_get_guint8( tvb, offset ) & 0x0f;
	/*offset += 1;*/ /* step over op_code */

	col_add_fstr( pinfo->cinfo, COL_INFO, "%s", val_to_str_const( op_code, op_code_vals_text, "Unknown" ));

	/* if ( tree ) */
		{
		/* create display subtree for the protocol */

		ti = proto_tree_add_protocol_format( tree, proto_netrom, tvb, 0, NETROM_HEADER_SIZE,
			"NET/ROM, Src: %s, Dst: %s",
			address_to_str(wmem_packet_scope(), &pinfo->src),
			address_to_str(wmem_packet_scope(), &pinfo->dst));

		netrom_tree = proto_item_add_subtree( ti, ett_netrom );

		offset = 0;

		/* source */
		proto_tree_add_item( netrom_tree, hf_netrom_src, tvb, offset, AX25_ADDR_LEN, ENC_NA );
		offset += AX25_ADDR_LEN;

		/* destination */
		proto_tree_add_item( netrom_tree, hf_netrom_dst, tvb, offset, AX25_ADDR_LEN, ENC_NA );
		offset += AX25_ADDR_LEN;

		/* ttl */
		proto_tree_add_item( netrom_tree, hf_netrom_ttl, tvb, offset, 1, ENC_BIG_ENDIAN );
		offset += 1;

		switch ( op_code )
			{
			case NETROM_PROTOEXT	:
						/* cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;
						break;
			case NETROM_CONNREQ	:
						/* cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;

						break;
			case NETROM_CONNACK	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* my cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* my cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_my_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						break;
			case NETROM_DISCREQ	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;

						break;
			case NETROM_DISCACK	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* unused */
						offset += 1;

						break;
			case NETROM_INFO	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* n_s */
						proto_tree_add_item( netrom_tree, hf_netrom_n_s, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* n_r */
						proto_tree_add_item( netrom_tree, hf_netrom_n_r, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						break;
			case NETROM_INFOACK	:
						/* your cct index */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_index, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* your cct id */
						proto_tree_add_item( netrom_tree, hf_netrom_your_cct_id, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						/* unused */
						offset += 1;

						/* n_r */
						proto_tree_add_item( netrom_tree, hf_netrom_n_r, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						break;
			default			:
						offset += 1;
						offset += 1;
						offset += 1;
						offset += 1;

						break;
			}

		/* type */
		dissect_netrom_type(	tvb,
					offset,
					pinfo,
					netrom_tree,
					hf_netrom_type,
					ett_netrom_type,
					&netrom_type_items
					);
		offset += 1;

		switch ( op_code )
			{
			case NETROM_PROTOEXT	:
						break;
			case NETROM_CONNREQ	:
						/* proposed window size */
						proto_tree_add_item( netrom_tree, hf_netrom_pwindow, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						proto_tree_add_item( netrom_tree, hf_netrom_user, tvb, offset, AX25_ADDR_LEN, ENC_NA );
						offset += AX25_ADDR_LEN;

						proto_tree_add_item( netrom_tree, hf_netrom_node, tvb, offset, AX25_ADDR_LEN, ENC_NA );
						offset += AX25_ADDR_LEN;

						break;
			case NETROM_CONNACK	:
						/* accepted window size */
						proto_tree_add_item( netrom_tree, hf_netrom_awindow, tvb, offset, 1, ENC_BIG_ENDIAN );
						offset += 1;

						break;
			case NETROM_DISCREQ	:
						break;
			case NETROM_DISCACK	:
						break;
			case NETROM_INFO	:
						break;
			case NETROM_INFOACK	:
						break;
			default			:
						break;
			}
		}

	/* Call sub-dissectors here */

	next_tvb = tvb_new_subset_remaining(tvb, offset);

	switch ( op_code )
		{
		case NETROM_PROTOEXT	:
					if ( cct_index == NETROM_PROTO_IP && cct_id == NETROM_PROTO_IP )
						call_dissector( ip_handle , next_tvb, pinfo, tree );
					else
						call_dissector( data_handle , next_tvb, pinfo, tree );

					break;
		case NETROM_INFO	:
		default			:
					call_dissector( data_handle , next_tvb, pinfo, tree );
					break;
		}
}
Exemplo n.º 7
0
static void
dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree     *clnp_tree;
    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;
    guint           next_length;
    proto_tree     *discpdu_tree;
    gboolean        save_in_error_pkt;
    fragment_head  *fd_head;
    tvbuff_t       *next_tvb;
    gboolean        update_col_info = TRUE;
    gboolean        save_fragmented;
    heur_dtbl_entry_t *hdtbl_entry;

    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");
        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);

    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, &ei_clnp_length,
                "Header length value < minimum length %u",
                FIXED_PART_LEN);
        return;
    }
    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);
    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_BIG_ENDIAN);

    /* 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);
    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, &ei_clnp_length,
                "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);
    switch (cksum_status) {
        default:
            /*
             * No checksum present, or not enough of the header present to
             * checksum it.
             */
            proto_tree_add_uint(clnp_tree, hf_clnp_checksum, tvb,
                    P_CLNP_CKSUM, 2,
                    cnf_cksum);
            break;

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

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

    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, &ei_clnp_length,
                "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, &ei_clnp_length,
                "Header length value < %u",
                FIXED_PART_LEN + 1 + dst_len);
        return;
    }
    nsel     = tvb_get_guint8(tvb, offset + dst_len - 1);
    TVB_SET_ADDRESS(&pinfo->net_dst, get_osi_address_type(), tvb, offset, dst_len);
    COPY_ADDRESS_SHALLOW(&pinfo->dst, &pinfo->net_dst);
    proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_dest, tvb, offset, dst_len,
            NULL,
            "%s",
            print_nsap_net(tvb, offset, 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, &ei_clnp_length,
                "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, &ei_clnp_length,
                "Header length value < %u",
                FIXED_PART_LEN + 1 + dst_len + 1 + src_len);
        return;
    }
    TVB_SET_ADDRESS(&pinfo->net_src, get_osi_address_type(), tvb, offset, src_len);
    COPY_ADDRESS_SHALLOW(&pinfo->src, &pinfo->net_src);
    proto_tree_add_bytes_format_value(clnp_tree, hf_clnp_src, tvb,
            offset, src_len,
            NULL,
            "%s",
            print_nsap_net(tvb, offset, 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, &ei_clnp_length,
                    "Header length value < %u",
                    FIXED_PART_LEN + 1 + dst_len + 1 + SEGMENTATION_PART_LEN);
            return;
        }

        du_id = tvb_get_ntohs(tvb, offset);
        proto_tree_add_item(clnp_tree, hf_clnp_data_unit_identifier, tvb, offset, 2, ENC_BIG_ENDIAN);
        segment_offset = tvb_get_ntohs(tvb, offset + 2);
        proto_tree_add_item(clnp_tree, hf_clnp_segment_offset, tvb, offset + 2 , 2, ENC_BIG_ENDIAN);
        total_length = tvb_get_ntohs(tvb, offset + 4);
        ti_tot_len = proto_tree_add_item(clnp_tree, hf_clnp_total_length, tvb, offset + 4 , 2, ENC_BIG_ENDIAN);
        if (total_length < segment_length) {
            /* Reassembled length is less than the length of this segment. */
            expert_add_info_format(pinfo, ti_tot_len, &ei_clnp_length,
                    "Total length < segment length %u", segment_length);
            return;
        }
        offset  += SEGMENTATION_PART_LEN;
        opt_len -= SEGMENTATION_PART_LEN;
    }

    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==NSEL_NET && tvb_get_guint8(next_tvb, 0)==NLPID_ISO10747_IDRP) {
                    if(call_dissector(idrp_handle, next_tvb, pinfo, tree) != 0) {
                        pinfo->fragmented = save_fragmented;
                        return;
                    }
                }
                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, &hdtbl_entry, 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. */
                    discpdu_tree = proto_tree_add_subtree(clnp_tree, tvb, offset, next_length,
                            ett_clnp_disc_pdu, NULL, "Discarded 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 */