Exemple #1
0
static void
dissect_conn_control(tvbuff_t *tvb, int offset, proto_tree *tree)
{
	guint8		conn_control;
	proto_item	*ti;
	proto_tree	*cc_tree;

	if (tree) {
		conn_control = tvb_get_guint8(tvb, offset);
		ti = proto_tree_add_text(tree, tvb, offset, 1,
		    "Connection control: 0x%02x", conn_control);
		cc_tree = proto_item_add_subtree(ti, ett_nbipx_conn_ctrl);
		proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
		      decode_boolean_bitfield(conn_control, 0x80, 8,
			      "System packet", "Non-system packet"));
		proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
		      decode_boolean_bitfield(conn_control, 0x40, 8,
			      "Acknowledgement required",
			      "Acknowledgement not required"));
		proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
		      decode_boolean_bitfield(conn_control, 0x20, 8,
			      "Attention", "No attention"));
		proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
		      decode_boolean_bitfield(conn_control, 0x10, 8,
			      "End of message", "No end of message"));
		proto_tree_add_text(cc_tree, tvb, offset, 1, "%s",
		      decode_boolean_bitfield(conn_control, 0x08, 8,
			      "Resend", "No resend"));
	}
}
static void
dissect_tacplus_body_acct_req( tvbuff_t* tvb, proto_tree *tree )
{
	int val, var_off;

	proto_item *tf;
	proto_tree *flags_tree;

	val=tvb_get_guint8( tvb, ACCT_Q_FLAGS_OFF );
	tf = proto_tree_add_uint( tree, hf_tacplus_acct_flags, tvb, ACCT_Q_FLAGS_OFF, 1, val );

	flags_tree = proto_item_add_subtree( tf, ett_tacplus_acct_flags );
	proto_tree_add_text( flags_tree, tvb, ACCT_Q_FLAGS_OFF, 1, "%s",
			decode_boolean_bitfield( val, TAC_PLUS_ACCT_FLAG_MORE, 8,
				"More: Set", "More: Not set" ) );
	proto_tree_add_text( flags_tree, tvb, ACCT_Q_FLAGS_OFF, 1, "%s",
			decode_boolean_bitfield( val, TAC_PLUS_ACCT_FLAG_START, 8,
				"Start: Set", "Start: Not set" ) );
	proto_tree_add_text( flags_tree, tvb, ACCT_Q_FLAGS_OFF, 1, "%s",
			decode_boolean_bitfield( val, TAC_PLUS_ACCT_FLAG_STOP, 8,
				"Stop: Set", "Stop: Not set" ) );
	proto_tree_add_text( flags_tree, tvb, ACCT_Q_FLAGS_OFF, 1, "%s",
			decode_boolean_bitfield( val, TAC_PLUS_ACCT_FLAG_WATCHDOG, 8,
				"Watchdog: Set", "Watchdog: Not set" ) );

	val=tvb_get_guint8( tvb, ACCT_Q_METHOD_OFF );
	proto_tree_add_text( tree, tvb, ACCT_Q_METHOD_OFF, 1,
			"Authen Method: 0x%01x (%s)",
			val, val_to_str( val, tacplus_authen_method, "Unknown Authen Method" ) );

	val=tvb_get_guint8( tvb, ACCT_Q_ARG_CNT_OFF );

	/* authen_type */
	var_off=proto_tree_add_tacplus_common_fields( tvb, tree ,
			ACCT_Q_PRIV_LVL_OFF,
			ACCT_Q_VARDATA_OFF+val
			);

	proto_tree_add_text( tree, tvb, ACCT_Q_ARG_CNT_OFF, 1,
			"Arg Cnt: %d", val  );

	dissect_tacplus_args_list( tvb, tree, var_off, ACCT_Q_VARDATA_OFF, val );


}
Exemple #3
0
static int
dissect_nfsacl_mask(tvbuff_t *tvb, int offset, proto_tree *tree, 
		const char *name)
{
	guint32 mask;
	proto_item *mask_item = NULL;
	proto_tree *mask_tree = NULL;

	mask = tvb_get_ntohl(tvb, offset + 0);

	if (tree)
	{
		mask_item = proto_tree_add_text(tree, tvb, offset, 4, "%s: 0x%02x",
				name, mask);

		if (mask_item)
			mask_tree = proto_item_add_subtree(mask_item, ett_nfsacl_mask);
	}

	if (mask_tree)
	{
		proto_tree_add_text(mask_tree, tvb, offset, 4, "%s",
				decode_boolean_bitfield(mask, 0x01, 8, "ACL entry", 
					"(no ACL entry)"));
		proto_tree_add_text(mask_tree, tvb, offset, 4, "%s",
				decode_boolean_bitfield(mask, 0x02, 8, "ACL count", 
					"(no ACL count)"));
		proto_tree_add_text(mask_tree, tvb, offset, 4, "%s",
				decode_boolean_bitfield(mask, 0x04, 8, "default ACL entry", 
					"(no default ACL entry)"));
		proto_tree_add_text(mask_tree, tvb, offset, 4, "%s",
				decode_boolean_bitfield(mask, 0x08, 8, "default ACL count", 
					"(no default ACL count)"));
	}

	offset += 4;
	return offset;
}
Exemple #4
0
/* dissect 9P Qid */
static void dissect_9P_qid(tvbuff_t * tvb,  proto_tree * tree,int offset)
{
	proto_item *qid_item,*qidtype_item;
	proto_tree *qid_tree,*qidtype_tree;
	guint64 path;
	guint32 vers;
	guint8 type;

	if(!tree)
		return;
	
	type = tvb_get_guint8(tvb,offset);
	vers = tvb_get_letohs(tvb,offset+1);
	path = tvb_get_letoh64(tvb,offset+1+4);

	qid_item = proto_tree_add_text(tree,tvb,offset,13,"Qid type=0x%02x vers=%d path=%" G_GINT64_MODIFIER "u",type,vers,path);
	qid_tree = proto_item_add_subtree(qid_item,ett_9P_qid);

	qidtype_item = proto_tree_add_item(qid_tree, hf_9P_qidtype, tvb, offset, 1, TRUE);
	qidtype_tree = proto_item_add_subtree(qidtype_item,ett_9P_qidtype);

	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(type,    QTDIR, 8, "Directory", "not a Directory"));
	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(type,    QTAPPEND, 8, "Append only", "not Append only"));
	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(type,    QTEXCL, 8, "Exclusive use", "not Exclusive use"));
	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(type,    QTMOUNT, 8, "Mounted channel", "not a Mounted channel"));
	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(type,    QTAUTH, 8, "Authentication file", "not an Authentication file"));
	proto_tree_add_text(qidtype_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(type,    QTTMP, 8, "Temporary file (not backed up)", "not a Temporary file"));

	proto_tree_add_item(qid_tree, hf_9P_qidvers, tvb, offset+1, 4, TRUE);
	proto_tree_add_item(qid_tree, hf_9P_qidpath, tvb, offset+1+4, 8, TRUE);
}
Exemple #5
0
/*
 * For PIM v2, see RFC 4601, RFC 3973 and draft-ietf-pim-sm-v2-new-03
 * (when PIM is run over IPv6, the rules for computing the PIM checksum
 * from the draft in question, not from RFC 2362, should be used).
 */
static void
dissect_pim(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
    int offset = 0;
    guint8 pim_typever;
    guint length, pim_length;
    guint16 pim_cksum, computed_cksum;
    vec_t cksum_vec[4];
    guint32 phdr[2];
    const char *typestr;
    proto_tree *pim_tree = NULL;
    proto_item *ti;
    proto_tree *pimopt_tree = NULL;
    proto_item *tiopt;

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

    pim_typever = tvb_get_guint8(tvb, 0);

    switch (PIM_VER(pim_typever)) {
    case 2:
        typestr = val_to_str(PIM_TYPE(pim_typever), type2vals, "Unknown (%u)");
        break;
    case 1:     /* PIMv1 - we should never see this */
    default:
        typestr = "Unknown";
        break;
    }

    if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
        col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "PIMv%d",
                     PIM_VER(pim_typever));
    }
    if (check_col(pinfo->cinfo, COL_INFO))
        col_add_str(pinfo->cinfo, COL_INFO, typestr);

    ti = proto_tree_add_item(tree, proto_pim, tvb, offset, -1, ENC_NA);
    pim_tree = proto_item_add_subtree(ti, ett_pim);

    proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(pim_tree, hf_pim_type, tvb, offset, 1, ENC_BIG_ENDIAN);
    proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset + 1, 1, ENC_NA);
    pim_cksum = tvb_get_ntohs(tvb, offset + 2);
    length = tvb_length(tvb);
    if (PIM_VER(pim_typever) == 2) {
        /*
         * Well, it's PIM v2, so we can check whether this is a Register
         * message, and thus can figure out how much to checksum and
         * whether to make the columns read-only.
         */
        if (PIM_TYPE(pim_typever) == 1) {
            /*
             * Register message - the PIM header is 8 bytes long.
             * Also set the columns non-writable. Otherwise the IPv4 or
             * IPv6 dissector for the encapsulated packet that caused
             * this register will overwrite the PIM info in the columns.
             */
            pim_length = 8;
            col_set_writable(pinfo->cinfo, FALSE);
        } else {
            /*
             * Other message - checksum the entire packet.
             */
            pim_length = tvb_reported_length(tvb);
        }
    } else {
        /*
         * We don't know what type of message this is, so say that
         * the length is 0, to force it not to be checksummed.
         */
        pim_length = 0;
    }
    if (!pinfo->fragmented && length >= pim_length) {
        /*
         * The packet isn't part of a fragmented datagram and isn't
         * truncated, so we can checksum it.
         */

        switch (pinfo->src.type) {
        case AT_IPv4:
            cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, pim_length);
            cksum_vec[0].len = pim_length;
            computed_cksum = in_cksum(&cksum_vec[0], 1);
            break;
        case AT_IPv6:
            /* Set up the fields of the pseudo-header. */
            cksum_vec[0].ptr = pinfo->src.data;
            cksum_vec[0].len = pinfo->src.len;
            cksum_vec[1].ptr = pinfo->dst.data;
            cksum_vec[1].len = pinfo->dst.len;
            cksum_vec[2].ptr = (const guint8 *)&phdr;
            phdr[0] = g_htonl(pim_length);
            phdr[1] = g_htonl(IP_PROTO_PIM);
            cksum_vec[2].len = 8;
            cksum_vec[3].ptr = tvb_get_ptr(tvb, 0, pim_length);
            cksum_vec[3].len = pim_length;
            computed_cksum = in_cksum(&cksum_vec[0], 4);
            break;
        default:
            /* PIM is available for IPv4 and IPv6 right now */
            computed_cksum = 0; /* squelch GCC complaints */
            DISSECTOR_ASSERT_NOT_REACHED();
            break;
        }

        if (computed_cksum == 0) {
            proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
                                       offset + 2, 2, pim_cksum,
                                       "Checksum: 0x%04x [correct]",
                                       pim_cksum);
        } else {
            proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
                                       offset + 2, 2, pim_cksum,
                                       "Checksum: 0x%04x [incorrect, should be 0x%04x]",
                                       pim_cksum, in_cksum_shouldbe(pim_cksum, computed_cksum));
        }
    } else {
        proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb,
                            offset + 2, 2, pim_cksum);
    }

    offset += 4;

    if (tvb_reported_length_remaining(tvb, offset) > 0) {
        tiopt = proto_tree_add_text(pim_tree, tvb, offset, -1, "PIM options");
        pimopt_tree = proto_item_add_subtree(tiopt, ett_pim_opts);
    } else
        goto done;

    if (PIM_VER(pim_typever) != 2)
        goto done;

    /* version 2 decoder */
    switch (PIM_TYPE(pim_typever)) {
    case 0:     /*hello*/
    {
        int opt_count = 0;

        while (tvb_reported_length_remaining(tvb, offset) >= 2) {
            guint16 hello_opt, opt_len;
            guint16 opt_value;
            proto_item *opt_item;
            proto_tree *opt_tree;

            opt_count++;
            hello_opt = tvb_get_ntohs(tvb, offset);
            opt_len = tvb_get_ntohs(tvb, offset + 2);
            opt_item = proto_tree_add_text(pimopt_tree, tvb, offset, 4 + opt_len,
                                           "Option %u: %s", hello_opt,
                                           val_to_str(hello_opt, pim_opt_vals, "Unknown: %u"));
            opt_tree = proto_item_add_subtree(opt_item, ett_pim_opt);
            proto_tree_add_item(opt_tree, hf_pim_optiontype, tvb, offset, 2, ENC_BIG_ENDIAN);
            proto_tree_add_item(opt_tree, hf_pim_optionlength, tvb, offset + 2, 2, ENC_BIG_ENDIAN);

            switch(hello_opt) {
            case 1: /* Hello Hold Time Option */
                opt_value = tvb_get_ntohs(tvb, offset + 4);
                proto_tree_add_uint_format(opt_tree, hf_pim_holdtime, tvb,
                                           offset + 4, opt_len, opt_value,
                                           "Holdtime: %us %s", opt_value, opt_value == 0 ? "(goodbye)" :
                                           opt_value == 0xffff ? "(infinity)": "");
                proto_item_append_text(opt_item, ": %us %s", opt_value,
                                       opt_value == 0 ? "(goodbye)" :
                                       opt_value == 0xffff ? "(infinity)": "");
                break;

            case 2: /* LAN Prune Delay Option */
                proto_tree_add_item(opt_tree, hf_pim_t, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
                proto_tree_add_item(opt_tree, hf_pim_propagation_delay, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
                proto_tree_add_item(opt_tree, hf_pim_override_interval, tvb, offset + 6, 2, ENC_BIG_ENDIAN);
                proto_item_append_text(opt_item,
                                       ": T = %u, Propagation Delay = %ums, Override Interval = %ums",
                                       tvb_get_guint8(tvb, offset + 4) & 0x80 ? 1 : 0,
                                       tvb_get_ntohs(tvb, offset + 4) & 0x7fff,
                                       tvb_get_ntohs(tvb, offset + 6));
                break;

            case 19: /* DR priority */
                proto_tree_add_item(opt_tree, hf_pim_dr_priority, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
                proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4));
                break;

            case 20: /* Generation ID */
                proto_tree_add_item(opt_tree, hf_pim_generation_id, tvb, offset + 4, 4, ENC_BIG_ENDIAN);
                proto_item_append_text(opt_item, ": %u", tvb_get_ntohl(tvb, offset + 4));
                break;

            case 21: /* State Refresh Capable Option */
                proto_tree_add_item(opt_tree, hf_pim_state_refresh_version, tvb, offset + 4, 1, ENC_BIG_ENDIAN);
                proto_tree_add_item(opt_tree, hf_pim_state_refresh_interval, tvb, offset + 5, 1, ENC_BIG_ENDIAN);
                proto_tree_add_item(opt_tree, hf_pim_state_refresh_reserved, tvb, offset + 6, 2, ENC_BIG_ENDIAN);
                proto_item_append_text(opt_item, ": Version = %u, Interval = %us",
                                       tvb_get_guint8(tvb, offset + 4),
                                       tvb_get_guint8(tvb, offset + 5));
                break;

            case 24: /* address list */
            case 65001: /* address list (old implementations) */
            {
                int i;
                proto_tree *sub_tree = NULL;
                proto_item *addrlist_option;

                addrlist_option = proto_tree_add_text(opt_tree, tvb, offset, 4 + opt_len,
                                                      "%sAddress List (%u)",
                                                      hello_opt == 65001 ? "old " : "",
                                                      hello_opt);
                sub_tree = proto_item_add_subtree(addrlist_option, ett_pim_opt);
                for (i = offset + 4; i < offset + 4 + opt_len; ) {
                    int advance;
                    const char *s;

                    s = dissect_pim_addr(tvb, i, pimv2_unicast, &advance);
                    if (s == NULL)
                        break;
                    proto_tree_add_text(sub_tree, tvb, offset,
                                        advance, "Address: %s", s);
                    i += advance;
                }
                break;
            }

            default:
                if (opt_len)
                    proto_tree_add_item(opt_tree, hf_pim_optionvalue, tvb,
                                        offset + 4, opt_len, ENC_NA);
                break;
            }
            offset += 4 + opt_len;
        }
        proto_item_append_text(tiopt, ": %u", opt_count);
        break;
    }

    case 1:     /* register */
    {
        guint32 flags;
        guint8 v_hl;
        tvbuff_t *next_tvb;
        proto_tree *flag_tree = NULL;
        proto_item *tiflag;

        flags = tvb_get_ntohl(tvb, offset);
        tiflag = proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                                     "Flags: 0x%08x", flags);
        flag_tree = proto_item_add_subtree(tiflag, ett_pim);
        proto_tree_add_text(flag_tree, tvb, offset, 1, "%s",
                            decode_boolean_bitfield(flags, 0x80000000, 32,
                                                    "Border", "Not border"));
        proto_tree_add_text(flag_tree, tvb, offset, 1, "%s",
                            decode_boolean_bitfield(flags, 0x40000000, 32,
                                                    "Null-Register", "Not Null-Register"));
        offset += 4;

        /*
         * The rest of the packet is a multicast data packet.
         */
        next_tvb = tvb_new_subset_remaining(tvb, offset);

        /*
         * It's an IP packet - determine whether it's IPv4 or IPv6.
         */
        v_hl = tvb_get_guint8(tvb, offset);
        switch((v_hl & 0xf0) >> 4) {
        case 0:     /* Null-Register dummy header.
                     * Has the same address family as the encapsulating PIM packet,
                     * e.g. an IPv6 data packet is encapsulated in IPv6 PIM packet.
                     */
            if (pinfo->src.type == AT_IPv4) {
                proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                    "IPv4 dummy header");
                proto_tree_add_text(pimopt_tree, tvb, offset + 12, 4,
                                    "Source: %s",
                                    tvb_ip_to_str(tvb, offset + 12));
                proto_tree_add_text(pimopt_tree, tvb, offset + 16, 4,
                                    "Group: %s",
                                    tvb_ip_to_str(tvb, offset + 16));
            } else if (pinfo->src.type == AT_IPv6) {
                proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                    "IPv6 dummy header");
                proto_tree_add_text(pimopt_tree, tvb,
                                    offset + 8, 16,
                                    "Source: %s",
                                    tvb_ip6_to_str(tvb, offset + 8));
                proto_tree_add_text(pimopt_tree, tvb,
                                    offset + 8 + 16, 16,
                                    "Group: %s",
                                    tvb_ip6_to_str(tvb, offset + 8 + 16));
            } else
                proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                    "Dummy header for an unknown protocol");
            break;
        case 4: /* IPv4 */
#if 0
            call_dissector(ip_handle, next_tvb, pinfo, tree);
#else
            call_dissector(ip_handle, next_tvb, pinfo, pimopt_tree);
#endif
            break;
        case 6: /* IPv6 */
#if 0
            call_dissector(ipv6_handle, next_tvb, pinfo, tree);
#else
            call_dissector(ipv6_handle, next_tvb, pinfo, pimopt_tree);
#endif
            break;
        default:
            proto_tree_add_text(pimopt_tree, tvb, offset, -1,
                                "Unknown IP version %d", (v_hl & 0xf0) >> 4);
            break;
        }
        break;
    }

    case 2:     /* register-stop */
    {
        int advance;
        const char *s;

        s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s);
        offset += advance;
        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s);
        break;
    }

    case 3:     /* join/prune */
    case 6:     /* graft */
    case 7:     /* graft-ack */
    {
        int advance;
        int off;
        const char *s;
        int ngroup, i, njoin, nprune, j;
        guint16 holdtime;
        proto_tree *grouptree = NULL;
        proto_item *tigroup;
        proto_tree *subtree = NULL;
        proto_item *tisub;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                            "Upstream-neighbor: %s", s);
        offset += advance;

        proto_tree_add_item(pimopt_tree, hf_pim_res_bytes, tvb, offset, 1, ENC_NA);
        offset += 1;    /* skip reserved field */

        ngroup = tvb_get_guint8(tvb, offset);
        proto_tree_add_item(pimopt_tree, hf_pim_numgroups, tvb, offset, 1, ENC_BIG_ENDIAN);
        offset += 1;

        holdtime = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb,
                                   offset, 2, holdtime,
                                   "Holdtime: %us %s", holdtime,
                                   holdtime == 0xffff ? "(infinity)": "");
        offset += 2;

        for (i = 0; i < ngroup; i++) {
            s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
            if (s == NULL)
                goto breakbreak3;
            tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                                          "Group %d: %s", i, s);
            grouptree = proto_item_add_subtree(tigroup, ett_pim);
            offset += advance;

            njoin = tvb_get_ntohs(tvb, offset);
            nprune = tvb_get_ntohs(tvb, offset + 2);
            tisub = proto_tree_add_item(grouptree, hf_pim_numjoins, tvb,
                                        offset, 2, ENC_BIG_ENDIAN);
            subtree = proto_item_add_subtree(tisub, ett_pim);
            off = offset + 4;
            for (j = 0; j < njoin; j++) {
                s = dissect_pim_addr(tvb, off, pimv2_source, &advance);
                if (s == NULL)
                    goto breakbreak3;
                proto_tree_add_text(subtree, tvb, off, advance,
                                    "IP address: %s", s);
                off += advance;
            }

            tisub = proto_tree_add_item(grouptree, hf_pim_numprunes, tvb,
                                        offset + 2, 2, ENC_BIG_ENDIAN);
            subtree = proto_item_add_subtree(tisub, ett_pim);
            for (j = 0; j < nprune; j++) {
                s = dissect_pim_addr(tvb, off, pimv2_source, &advance);
                if (s == NULL)
                    goto breakbreak3;
                proto_tree_add_text(subtree, tvb, off, advance,
                                    "IP address: %s", s);
                off += advance;
            }
            offset = off;
        }
    breakbreak3:
        break;
    }

    case 4:     /* bootstrap */
    {
        const char *s;
        int advance;
        int i, j;
        int frpcnt;
        guint16 holdtime;
        proto_tree *grouptree = NULL;
        proto_item *tigroup;

        proto_tree_add_text(pimopt_tree, tvb, offset, 2,
                            "Fragment tag: 0x%04x", tvb_get_ntohs(tvb, offset));
        offset += 2;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Hash mask len: %u", tvb_get_guint8(tvb, offset));
        offset += 1;
        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "BSR priority: %u", tvb_get_guint8(tvb, offset));
        offset += 1;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "BSR: %s", s);
        offset += advance;

        for (i = 0; tvb_reported_length_remaining(tvb, offset) > 0; i++) {
            s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
            if (s == NULL)
                goto breakbreak4;
            tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                                          "Group %d: %s", i, s);
            grouptree = proto_item_add_subtree(tigroup, ett_pim);
            offset += advance;

            proto_tree_add_text(grouptree, tvb, offset, 1,
                                "RP count: %u", tvb_get_guint8(tvb, offset));
            offset += 1;
            frpcnt = tvb_get_guint8(tvb, offset);
            proto_tree_add_text(grouptree, tvb, offset, 1,
                                "FRP count: %u", frpcnt);
            offset += 3;

            for (j = 0; j < frpcnt; j++) {
                s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
                if (s == NULL)
                    goto breakbreak4;
                proto_tree_add_text(grouptree, tvb, offset, advance,
                                    "RP %d: %s", j, s);
                offset += advance;

                holdtime = tvb_get_ntohs(tvb, offset);
                proto_tree_add_uint_format(grouptree, hf_pim_holdtime, tvb,
                                   offset, 2, holdtime,
                                   "Holdtime: %us %s", holdtime,
                                   holdtime == 0xffff ? "(infinity)": "");
                offset += 2;
                proto_tree_add_text(grouptree, tvb, offset, 1,
                                    "Priority: %u", tvb_get_guint8(tvb, offset));
                offset += 2;    /* also skips reserved field */
            }
        }

    breakbreak4:
        break;
    }

    case 5:     /* assert */
    {
        const char *s;
        int advance;
        guint32 pref;

        s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Group: %s", s);
        offset += advance;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "Source: %s", s);
        offset += advance;

        proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, ENC_BIG_ENDIAN);
        pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff;
        proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb,
                                   offset, 4, pref,
                                   "Metric Preference: %u", pref);
        offset += 4;

        proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;
        break;
    }

    case 8:     /* Candidate-RP-Advertisement */
    {
        const char *s;
        int advance;
        int pfxcnt;
        guint16 holdtime;
        int i;

        pfxcnt = tvb_get_guint8(tvb, offset);
        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Prefix-count: %u", pfxcnt);
        offset += 1;
        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Priority: %u", tvb_get_guint8(tvb, offset));
        offset += 1;
        holdtime = tvb_get_ntohs(tvb, offset);
        proto_tree_add_uint_format(pimopt_tree, hf_pim_holdtime, tvb,
                                   offset, 2, holdtime,
                                   "Holdtime: %us %s", holdtime,
                                   holdtime == 0xffff ? "(infinity)": "");
        offset += 2;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance, "RP: %s", s);
        offset += advance;

        for (i = 0; i < pfxcnt; i++) {
            s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
            if (s == NULL)
                goto breakbreak8;
            proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                                "Group %d: %s", i, s);
            offset += advance;
        }
    breakbreak8:
        break;
    }

    case 9:     /* State-Refresh */
    {
        const char *s;
        int advance;
        guint32 pref;

        s = dissect_pim_addr(tvb, offset, pimv2_group, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                            "Group: %s", s);
        offset += advance;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                            "Source: %s", s);
        offset += advance;

        s = dissect_pim_addr(tvb, offset, pimv2_unicast, &advance);
        if (s == NULL)
            break;
        proto_tree_add_text(pimopt_tree, tvb, offset, advance,
                            "Originator: %s", s);
        offset += advance;

        proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, ENC_BIG_ENDIAN);
        pref = tvb_get_ntohl(tvb, offset) & 0x7fffffff;
        proto_tree_add_uint_format(pimopt_tree, hf_pim_metric_pref, tvb,
                                   offset, 4, pref,
                                   "Metric Preference: %u", pref);
        offset += 4;

        proto_tree_add_item(pimopt_tree, hf_pim_metric, tvb, offset, 4, ENC_BIG_ENDIAN);
        offset += 4;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Masklen: %u", tvb_get_guint8(tvb, offset));
        offset += 1;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "TTL: %u", tvb_get_guint8(tvb, offset));
        offset += 1;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune indicator %s",
                            decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x80, 8,
                                                    "set", "clear"));
        proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Prune now %s",
                            decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x40, 8,
                                                    "set", "clear"));
        proto_tree_add_text(pimopt_tree, tvb, offset, 1, "Assert override %s",
                            decode_boolean_bitfield(tvb_get_guint8(tvb, offset), 0x20, 8,
                                                    "set", "clear"));
        offset += 1;

        proto_tree_add_text(pimopt_tree, tvb, offset, 1,
                            "Interval: %u", tvb_get_guint8(tvb, offset));
        offset += 1;

        break;
    }

    default:
        break;
    }
done:;
}
Exemple #6
0
/*dissect 9P stat mode and create perm flags */
static void dissect_9P_dm(tvbuff_t * tvb,  proto_item * item,int offset,int iscreate)
{
	proto_item *mode_tree;
	guint32 dm;


	dm = tvb_get_letohl(tvb,offset);
	mode_tree = proto_item_add_subtree(item, ett_9P_dm);
	if(!mode_tree)
		return;

	proto_tree_add_text(mode_tree, tvb, offset, 1, "%s",
	decode_boolean_bitfield(dm,    DMDIR, 32, "Directory", "not a Directory"));
	if(!iscreate) { /* Not applicable to Tcreate (?) */
		proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
		decode_boolean_bitfield(dm,    DMAPPEND, 32, "Append only", "not Append only"));
		proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
		decode_boolean_bitfield(dm,    DMEXCL, 32, "Exclusive use", "not Exclusive use"));
		proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
		decode_boolean_bitfield(dm,    DMMOUNT, 32, "Mounted channel", "not a Mounted channel"));
		proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
		decode_boolean_bitfield(dm,    DMAUTH, 32, "Authentication file", "not an Authentication file"));
		proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
		decode_boolean_bitfield(dm,    DMTMP, 32, "Temporary file (not backed up)", "not a Temporary file"));
	}

	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
	decode_boolean_bitfield(dm,    0400, 32, "Read permission for owner", "no Read permission for owner"));
	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
	decode_boolean_bitfield(dm,    0200, 32, "Write permission for owner", "no Write permission for owner"));
	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
	decode_boolean_bitfield(dm,    0100, 32, "Execute permission for owner", "no Execute permission for owner"));
	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
	decode_boolean_bitfield(dm,     040, 32, "Read permission for group", "no Read permission for group"));
	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
	decode_boolean_bitfield(dm,     020, 32, "Write permission for group", "no Write permission for group"));
	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
	decode_boolean_bitfield(dm,     010, 32, "Execute permission for group", "no Execute permission for group"));
	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
	decode_boolean_bitfield(dm,      04, 32, "Read permission for others", "no Read permission for others"));
	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
	decode_boolean_bitfield(dm,      02, 32, "Write permission for others", "no Write permission for others"));
	proto_tree_add_text(mode_tree, tvb, offset, 4, "%s",
	decode_boolean_bitfield(dm,      01, 32, "Execute permission for others", "no Execute permission for others"));
}
Exemple #7
0
static void
dissect_nbipx(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	gboolean	has_routes;
	proto_tree	*nbipx_tree = NULL;
	proto_item	*ti = NULL;
	int		offset = 0;
	guint8		packet_type;
	guint8		name_type_flag;
	proto_tree	*name_type_flag_tree;
	proto_item	*tf;
	char		name[(NETBIOS_NAME_LEN - 1)*4 + 1];
	int		name_type;
	gboolean	has_payload;
	tvbuff_t	*next_tvb;

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

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

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

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

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

	packet_type = tvb_get_guint8(tvb, offset + 1);

	switch (packet_type) {

	case NBIPX_FIND_NAME:
	case NBIPX_NAME_RECOGNIZED:
	case NBIPX_CHECK_NAME:
	case NBIPX_NAME_IN_USE:
	case NBIPX_DEREGISTER_NAME:
		name_type_flag = tvb_get_guint8(tvb, offset);
		name_type = get_netbios_name(tvb, offset+2, name, (NETBIOS_NAME_LEN - 1)*4 + 1);
		if (check_col(pinfo->cinfo, COL_INFO)) {
			col_add_fstr(pinfo->cinfo, COL_INFO, "%s %s<%02x>",
				val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"),
				name, name_type);
		}
		if (nbipx_tree) {
			tf = proto_tree_add_text(nbipx_tree, tvb, offset, 1,
				"Name type flag: 0x%02x", name_type_flag);
			name_type_flag_tree = proto_item_add_subtree(tf,
					ett_nbipx_name_type_flags);
			proto_tree_add_text(name_type_flag_tree, tvb, offset,
			    1, "%s",
			    decode_boolean_bitfield(name_type_flag, 0x80, 8,
			      "Group name", "Unique name"));
			proto_tree_add_text(name_type_flag_tree, tvb, offset,
			    1, "%s",
			    decode_boolean_bitfield(name_type_flag, 0x40, 8,
			      "Name in use", "Name not used"));
			proto_tree_add_text(name_type_flag_tree, tvb, offset,
			    1, "%s",
			    decode_boolean_bitfield(name_type_flag, 0x04, 8,
			      "Name registered", "Name not registered"));
			proto_tree_add_text(name_type_flag_tree, tvb, offset,
			    1, "%s",
			    decode_boolean_bitfield(name_type_flag, 0x02, 8,
			      "Name duplicated", "Name not duplicated"));
			proto_tree_add_text(name_type_flag_tree, tvb, offset,
			    1, "%s",
			    decode_boolean_bitfield(name_type_flag, 0x01, 8,
			      "Name deregistered", "Name not deregistered"));
		}
		offset += 1;

		dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
		offset += 1;

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

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

	case NBIPX_SESSION_DATA:
	case NBIPX_SESSION_END:
	case NBIPX_SESSION_END_ACK:
		if (check_col(pinfo->cinfo, COL_INFO)) {
			col_add_str(pinfo->cinfo, COL_INFO,
				val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
		}
		dissect_conn_control(tvb, offset, nbipx_tree);
		offset += 1;

		dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
		offset += 1;

		if (nbipx_tree) {
			proto_tree_add_text(nbipx_tree, tvb, offset, 2,
			    "Source connection ID: 0x%04X",
			    tvb_get_letohs(tvb, offset));
		}
		offset += 2;

		if (nbipx_tree) {
			proto_tree_add_text(nbipx_tree, tvb, offset, 2,
			    "Destination connection ID: 0x%04X",
			    tvb_get_letohs(tvb, offset));
		}
		offset += 2;

		if (nbipx_tree) {
			proto_tree_add_text(nbipx_tree, tvb, offset, 2,
			    "Send sequence number: %u",
			    tvb_get_letohs(tvb, offset));
		}
		offset += 2;

		if (nbipx_tree) {
			proto_tree_add_text(nbipx_tree, tvb, offset, 2,
			    "Total data length: %u",
			    tvb_get_letohs(tvb, offset));
		}
		offset += 2;

		if (nbipx_tree) {
			proto_tree_add_text(nbipx_tree, tvb, offset, 2,
			    "Offset: %u",
			    tvb_get_letohs(tvb, offset));
		}
		offset += 2;

		if (nbipx_tree) {
			proto_tree_add_text(nbipx_tree, tvb, offset, 2,
			    "Data length: %u",
			    tvb_get_letohs(tvb, offset));
		}
		offset += 2;

		if (nbipx_tree) {
			proto_tree_add_text(nbipx_tree, tvb, offset, 2,
			    "Receive sequence number: %u",
			    tvb_get_letohs(tvb, offset));
		}
		offset += 2;

		if (nbipx_tree) {
			proto_tree_add_text(nbipx_tree, tvb, offset, 2,
			    "Bytes received: %u",
			    tvb_get_letohs(tvb, offset));
		}
		offset += 2;

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

	case NBIPX_DIRECTED_DATAGRAM:
		if (check_col(pinfo->cinfo, COL_INFO)) {
			col_add_str(pinfo->cinfo, COL_INFO, 
				val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
		}
		dissect_conn_control(tvb, offset, nbipx_tree);
		offset += 1;

		dissect_packet_type(tvb, offset, packet_type, nbipx_tree);
		offset += 1;

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

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

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

	default:
		if (check_col(pinfo->cinfo, COL_INFO)) {
			col_add_str(pinfo->cinfo, COL_INFO, 
				val_to_str(packet_type, nbipx_data_stream_type_vals, "Unknown"));
		}

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

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

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

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

	if (has_payload && tvb_offset_exists(tvb, offset)) {
		next_tvb = tvb_new_subset_remaining(tvb, offset);
		dissect_netbios_payload(next_tvb, pinfo, tree);
	}
}
Exemple #8
0
static void
dissect_lsp_link_info_clv(tvbuff_t *tvb, proto_tree *tree, int offset,
    int length)
{
	guint8 flags_cost;

	if (length < 1) {
		nlsp_dissect_unknown(tvb, tree, offset,
		    "Short link info entry");
		return;
	}
	if (tree) {
		flags_cost = tvb_get_guint8(tvb, offset);
		proto_tree_add_text(tree, tvb, offset, 1, "%s",
		    decode_boolean_bitfield(flags_cost, 0x80, 1*8,
			"Cost not present", "Cost present"));
		if (!(flags_cost & 0x80)) {
			/*
			 * 0x80 clear => cost present.
			 */
			proto_tree_add_text(tree, tvb, offset, 1, "%s",
			    decode_boolean_bitfield(flags_cost, 0x40, 1*8,
				"Cost is internal metric",
				"Cost is external metric"));
			proto_tree_add_text(tree, tvb, offset, 1, "%s",
			    decode_numeric_bitfield(flags_cost, 0x3F, 1*8,
				"Cost = %u"));
		}
	}
	offset += 1;
	length -= 1;

	if (length < 3) {
		nlsp_dissect_unknown(tvb, tree, offset,
		    "Short link info entry");
		return;
	}
	offset += 3;	/* Reserved */
	length -= 3;

	if (length < 7) {
		nlsp_dissect_unknown(tvb, tree, offset,
		    "Short link info entry");
		return;
	}
	if (tree) {
		proto_tree_add_text(tree, tvb, offset, 6,
		    "Router System ID: %s",
		    tvb_ether_to_str(tvb, offset));
		proto_tree_add_text(tree, tvb, offset+6, 1,
		    "Router Pseudonode ID: %u",
		    tvb_get_guint8(tvb, offset+6));
	}
	offset += 7;
	length -= 7;

	if (length < 4) {
		nlsp_dissect_unknown(tvb, tree, offset,
		    "Short link info entry");
		return;
	}
	if (tree) {
		proto_tree_add_text(tree, tvb, offset, 4,
		    "MTU Size: %u",
		    tvb_get_ntohl(tvb, offset));
	}
	offset += 4;
	length -= 4;

	if (length < 4) {
		nlsp_dissect_unknown(tvb, tree, offset,
		    "Short link info entry");
		return;
	}
	if (tree) {
		proto_tree_add_text(tree, tvb, offset, 4,
		    "Delay: %uus",
		    tvb_get_ntohl(tvb, offset));
	}
	offset += 4;
	length -= 4;

	if (length < 4) {
		nlsp_dissect_unknown(tvb, tree, offset,
		    "Short link info entry");
		return;
	}
	if (tree) {
		proto_tree_add_text(tree, tvb, offset, 4,
		    "Throughput: %u bits/s",
		    tvb_get_ntohl(tvb, offset));
	}
	offset += 4;
	length -= 4;

	if (length < 2) {
		nlsp_dissect_unknown(tvb, tree, offset,
		    "Short link info entry");
		return;
	}
	if (tree) {
		proto_tree_add_text(tree, tvb, offset, 2,
		    "Media type: %s",
		    val_to_str(tvb_get_ntohs(tvb, offset), media_type_vals,
			"Unknown (0x%04x)"));
	}
	offset += 2;
	length -= 2;
}
static void
dissect_cups(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree	*cups_tree = 0;
	proto_tree	*ptype_subtree = 0;
	proto_item	*ti = 0;
	gint		offset = 0;
	gint		next_offset;
	guint		len;
	unsigned int	u;
	const guint8	*str;
	cups_ptype_t	ptype;
	unsigned int	state;

	if (check_col(pinfo->cinfo, COL_PROTOCOL))
		col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_TAG_CUPS);
	col_clear(pinfo->cinfo, COL_INFO);

	if (tree) {
		ti = proto_tree_add_item(tree, proto_cups, tvb, offset, -1,
		    FALSE);
		cups_tree = proto_item_add_subtree(ti, ett_cups);
	}

	/* Format (1450 bytes max.):  */
	/* type state uri ["location" ["info" ["make-and-model"]]]\n */

	ptype = get_hex_uint(tvb, offset, &next_offset);
	len = next_offset - offset;
	if (len != 0) {
		if (cups_tree) {
			ti = proto_tree_add_uint(cups_tree, hf_cups_ptype,
			    tvb, offset, len, ptype);
			ptype_subtree = proto_item_add_subtree(ti,
			    ett_cups_ptype);
			for (u = 0; u < N_CUPS_PTYPE_BITS; u++) {
				proto_tree_add_text(ptype_subtree, tvb,
				    offset, len, "%s",
				    decode_boolean_bitfield(ptype,
				      cups_ptype_bits[u].bit, sizeof (ptype)*8,
				      cups_ptype_bits[u].on_string,
				      cups_ptype_bits[u].off_string));
			}
		}
	}
	offset = next_offset;

	if (!skip_space(tvb, offset, &next_offset))
		return;	/* end of packet */
	offset = next_offset;

	state = get_hex_uint(tvb, offset, &next_offset);
	len = next_offset - offset;
	if (len != 0) {
		if (cups_tree)
			proto_tree_add_uint(cups_tree, hf_cups_state,
			    tvb, offset, len, state);
	}
	offset = next_offset;

	if (!skip_space(tvb, offset, &next_offset))
		return;	/* end of packet */
	offset = next_offset;

	str = get_unquoted_string(tvb, offset, &next_offset, &len);
	if (str == NULL)
		return;	/* separator/terminator not found */
	if (cups_tree)
		proto_tree_add_text(cups_tree, tvb, offset, len,
		    "URI: %.*s",
		    (guint16) len, str);
	if (check_col(pinfo->cinfo, COL_INFO))
		col_add_fstr(pinfo->cinfo, COL_INFO,
		    "%.*s (%s)",
		    (guint16) len, str,
		    val_to_str(state, cups_state_values, "0x%x"));
	offset = next_offset;

	if (!cups_tree)
		return;

	if (!skip_space(tvb, offset, &next_offset))
		return;	/* end of packet */
	offset = next_offset;

	str = get_quoted_string(tvb, offset, &next_offset, &len);
	if (str == NULL)
		return;	/* separator/terminator not found */
	proto_tree_add_text(cups_tree, tvb, offset+1, len,
	    "Location: \"%.*s\"",
	    (guint16) len, str);
	offset = next_offset;

	if (!skip_space(tvb, offset, &next_offset))
		return;	/* end of packet */
	offset = next_offset;

	str = get_quoted_string(tvb, offset, &next_offset, &len);
	if (str == NULL)
		return;	/* separator/terminator not found */
	proto_tree_add_text(cups_tree, tvb, offset+1, len,
	    "Information: \"%.*s\"",
	    (guint16) len, str);
	offset = next_offset;

	if (!skip_space(tvb, offset, &next_offset))
		return;	/* end of packet */
	offset = next_offset;

	str = get_quoted_string(tvb, offset, &next_offset, &len);
	if (str == NULL)
		return;	/* separator/terminator not found */
	proto_tree_add_text(cups_tree, tvb, offset+1, len,
	    "Make and model: \"%.*s\"",
	    (guint16) len, str);
	offset = next_offset;

	return;
}
Exemple #10
0
static void
dissect_clnp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_tree     *clnp_tree = NULL;
  proto_item     *ti;
  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         cnf_cksum;
  cksum_status_t  cksum_status;
  int             offset;
  guchar          src_len, dst_len, nsel, opt_len = 0;
  const guint8   *dst_addr, *src_addr;
  guint           next_length;
  proto_tree     *discpdu_tree;
  gboolean        save_in_error_pkt;
  fragment_data  *fd_head;
  tvbuff_t       *next_tvb;
  gboolean        update_col_info = TRUE;
  gboolean        save_fragmented;

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

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

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

  /* fixed part decoding */
  cnf_hdr_len = tvb_get_guint8(tvb, P_CLNP_HDR_LEN);
  opt_len = cnf_hdr_len;

  if (tree) {
    ti = proto_tree_add_item(tree, proto_clnp, tvb, 0, cnf_hdr_len, ENC_NA);
    clnp_tree = proto_item_add_subtree(ti, ett_clnp);
    proto_tree_add_uint(clnp_tree, hf_clnp_id, tvb, P_CLNP_PROTO_ID, 1,
                        cnf_proto_id);
    proto_tree_add_uint(clnp_tree, hf_clnp_length, tvb, P_CLNP_HDR_LEN, 1,
                        cnf_hdr_len);
    proto_tree_add_uint(clnp_tree, hf_clnp_version, tvb, P_CLNP_VERS, 1,
                        cnf_vers);
    cnf_ttl = tvb_get_guint8(tvb, P_CLNP_TTL);
    proto_tree_add_uint_format(clnp_tree, hf_clnp_ttl, tvb, P_CLNP_TTL, 1,
                               cnf_ttl,
                               "Holding Time : %u (%u.%u secs)",
                               cnf_ttl, cnf_ttl / 2, (cnf_ttl % 2) * 5);
  }

  cnf_type = tvb_get_guint8(tvb, P_CLNP_TYPE);
  pdu_type_string = val_to_str(cnf_type & CNF_TYPE, npdu_type_abbrev_vals,
                               "Unknown (0x%02x)");
  flag_string[0] = '\0';
  if (cnf_type & CNF_SEG_OK)
    g_strlcat(flag_string, "S ", 7);
  if (cnf_type & CNF_MORE_SEGS)
    g_strlcat(flag_string, "M ", 7);
  if (cnf_type & CNF_ERR_OK)
    g_strlcat(flag_string, "E ", 7);
  if (tree) {
    ti = proto_tree_add_uint_format(clnp_tree, hf_clnp_type, tvb, P_CLNP_TYPE, 1,
                                    cnf_type,
                                    "PDU Type     : 0x%02x (%s%s)",
                                    cnf_type,
                                    flag_string,
                                    pdu_type_string);
    type_tree = proto_item_add_subtree(ti, ett_clnp_type);
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_boolean_bitfield(cnf_type, CNF_SEG_OK, 8,
                                                "Segmentation permitted",
                                                "Segmentation not permitted"));
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_boolean_bitfield(cnf_type, CNF_MORE_SEGS, 8,
                                                "More segments",
                                                "Last segment"));
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_boolean_bitfield(cnf_type, CNF_ERR_OK, 8,
                                                "Report error if PDU discarded",
                                                "Don't report error if PDU discarded"));
    proto_tree_add_text(type_tree, tvb, P_CLNP_TYPE, 1, "%s",
                        decode_enumerated_bitfield(cnf_type, CNF_TYPE, 8,
                                                   npdu_type_vals, "%s"));
  }

  /* 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);
  cnf_cksum = tvb_get_ntohs(tvb, P_CLNP_CKSUM);
  cksum_status = calc_checksum(tvb, 0, cnf_hdr_len, cnf_cksum);
  if (tree) {
    proto_tree_add_uint(clnp_tree, hf_clnp_pdu_length, tvb, P_CLNP_SEGLEN, 2,
                        segment_length);
    switch (cksum_status) {

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

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

    case CKSUM_NOT_OK:
      /*
       * Checksum is not correct.
       */
      proto_tree_add_uint_format(clnp_tree, hf_clnp_checksum, tvb,
                                 P_CLNP_CKSUM, 2,
                                 cnf_cksum,
                                 "Checksum     : 0x%04x (incorrect)",
                                 cnf_cksum);
      break;
    }
    opt_len -= 9; /* Fixed part of Hesder */
  } /* tree */

  /* address part */

  offset = P_CLNP_ADDRESS_PART;
  dst_len  = tvb_get_guint8(tvb, offset);
  dst_addr = tvb_get_ptr(tvb, offset + 1, dst_len);
  nsel     = tvb_get_guint8(tvb, offset + dst_len);
  src_len  = tvb_get_guint8(tvb, offset + dst_len + 1);
  src_addr = tvb_get_ptr(tvb, offset + dst_len + 2, src_len);

  if (tree) {
    proto_tree_add_uint(clnp_tree, hf_clnp_dest_length, tvb, offset, 1,
                        dst_len);
    proto_tree_add_bytes_format(clnp_tree, hf_clnp_dest, tvb, offset + 1 , dst_len,
                                dst_addr,
                                " DA : %s",
                                print_nsap_net(dst_addr, dst_len));
    proto_tree_add_uint(clnp_tree, hf_clnp_src_length, tvb,
                        offset + 1 + dst_len, 1, src_len);
    proto_tree_add_bytes_format(clnp_tree, hf_clnp_src, tvb,
                                offset + dst_len + 2, src_len,
                                src_addr,
                                " SA : %s",
                                print_nsap_net(src_addr, src_len));

    opt_len -= dst_len + src_len +2;
  }

  SET_ADDRESS(&pinfo->net_src, AT_OSI, src_len, src_addr);
  SET_ADDRESS(&pinfo->src, AT_OSI, src_len, src_addr);
  SET_ADDRESS(&pinfo->net_dst, AT_OSI, dst_len, dst_addr);
  SET_ADDRESS(&pinfo->dst, AT_OSI, dst_len, dst_addr);

  /* Segmentation Part */

  offset += dst_len + src_len + 2;

  if (cnf_type & CNF_SEG_OK) {
#if 0
    struct clnp_segment seg;                                /* XXX - not used */
    tvb_memcpy(tvb, (guint8 *)&seg, offset, sizeof(seg));   /* XXX - not used */
#endif

    segment_offset = tvb_get_ntohs(tvb, offset + 2);
    du_id = tvb_get_ntohs(tvb, offset);
    if (tree) {
      proto_tree_add_text(clnp_tree, tvb, offset, 2,
                          "Data unit identifier: %06u",
                          du_id);
      proto_tree_add_text(clnp_tree, tvb, offset + 2 , 2,
                          "Segment offset      : %6u",
                          segment_offset);
      proto_tree_add_text(clnp_tree, tvb, offset + 4 , 2,
                          "Total length        : %6u",
                          tvb_get_ntohs(tvb, offset + 4));
    }

    offset  += 6;
    opt_len -= 6;
  }

  if (tree) {
    /* To do : decode options  */
#if 0
    proto_tree_add_text(clnp_tree, tvb, offset,
                        cnf_hdr_len - offset,
                        "Options/Data: <not shown>");
#endif
/* QUICK HACK Option Len:= PDU_Hd_length-( FixedPart+AddresPart+SegmentPart )*/

    dissect_osi_options( opt_len,
                         tvb, offset, clnp_tree );
  }

  offset = cnf_hdr_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(tvb, offset, pinfo, du_id, clnp_segment_table,
                                 clnp_reassembled_table, 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. */
      next_tvb = tvb_new_subset_remaining(tvb, offset);

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

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

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

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

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

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

      break;

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

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

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

          call_dissector(clnp_handle, next_tvb, pinfo, discpdu_tree);

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

    case ERQ_NPDU:
    case ERP_NPDU:
      /* XXX - dissect this */
      break;
    }
  }
  col_add_fstr(pinfo->cinfo, COL_INFO, "%s NPDU %s", pdu_type_string, flag_string);
  call_dissector(data_handle,next_tvb, pinfo, tree);
  pinfo->fragmented = save_fragmented;
} /* dissect_clnp */