Esempio n. 1
0
static void
dissect_btobex(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_item    *ti;
    proto_tree    *st;
    fragment_data *frag_msg       = NULL;
    gboolean       save_fragmented, complete;
    tvbuff_t*      new_tvb        = NULL;
    tvbuff_t*      next_tvb       = NULL;
    guint32        no_of_segments = 0;
    int            offset         = 0;

    save_fragmented = pinfo->fragmented;

    frag_msg = NULL;
    complete = FALSE;

    if (fragment_get(pinfo, pinfo->p2p_dir, fragment_table)) {
        /* not the first fragment */
        frag_msg = fragment_add_seq_next(tvb, 0, pinfo, pinfo->p2p_dir,
                                fragment_table, reassembled_table, tvb_length(tvb), TRUE);

        new_tvb = process_reassembled_data(tvb, 0, pinfo,
                        "Reassembled Obex packet", frag_msg, &btobex_frag_items, NULL, tree);

        pinfo->fragmented = TRUE;
    }
    else    {
        if (tvb_length(tvb) < tvb_get_ntohs(tvb, offset+1)) {
            /* first fragment in a sequence */
            no_of_segments = tvb_get_ntohs(tvb, offset+1)/tvb_length(tvb);
            if (tvb_get_ntohs(tvb, offset+1) > (no_of_segments * tvb_length(tvb)))
                no_of_segments++;

            frag_msg = fragment_add_seq_next(tvb, 0, pinfo, pinfo->p2p_dir,
                                fragment_table, reassembled_table, tvb_length(tvb), TRUE);

            fragment_set_tot_len(pinfo, pinfo->p2p_dir, fragment_table, no_of_segments-1);

            new_tvb = process_reassembled_data(tvb, 0, pinfo,
                        "Reassembled Obex packet", frag_msg, &btobex_frag_items, NULL, tree);

            pinfo->fragmented = TRUE;
            }
        else if (tvb_length(tvb) == tvb_get_ntohs(tvb, offset+1)) {
            /* non-fragmented */
            complete = TRUE;
            pinfo->fragmented = FALSE;
        }
    }

    if (new_tvb) { /* take it all */
        next_tvb = new_tvb;
        complete = TRUE;
    }
    else { /* make a new subset */
        next_tvb = tvb_new_subset_remaining(tvb, offset);
    }

    if (complete) {
        guint8 code, final_flag;

        /* fully dissectable packet ready */
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "OBEX");

        ti = proto_tree_add_item(tree, proto_btobex, next_tvb, 0, -1, ENC_NA);
        st = proto_item_add_subtree(ti, ett_btobex);

        /* op/response code */
        code = tvb_get_guint8(next_tvb, offset) & BTOBEX_CODE_VALS_MASK;
        final_flag = tvb_get_guint8(next_tvb, offset) & 0x80;

        switch (pinfo->p2p_dir)
        {
        case P2P_DIR_SENT:
            col_add_fstr(pinfo->cinfo, COL_INFO, "Sent ");
            break;

        case P2P_DIR_RECV:
            col_add_fstr(pinfo->cinfo, COL_INFO, "Rcvd ");
            break;

        case P2P_DIR_UNKNOWN:
            break;

        default:
            col_add_fstr(pinfo->cinfo, COL_INFO, "Unknown direction %d ",
                pinfo->p2p_dir);
            break;
        }

        col_append_fstr(pinfo->cinfo, COL_INFO, "%s",
                        val_to_str_ext_const(code, &code_vals_ext, "Unknown"));

        if ((code < BTOBEX_CODE_VALS_CONTINUE) || (code == BTOBEX_CODE_VALS_ABORT)) {
            proto_tree_add_item(st, hf_opcode, next_tvb, offset, 1, ENC_BIG_ENDIAN);
            if (pinfo->p2p_dir == P2P_DIR_SENT || pinfo->p2p_dir == P2P_DIR_RECV) {
                last_opcode[pinfo->p2p_dir] = code;
            }
            }
        else    {
            proto_tree_add_item(st, hf_response_code, next_tvb, offset, 1, ENC_BIG_ENDIAN);
            }
        proto_tree_add_item(st, hf_final_flag, next_tvb, offset, 1, ENC_BIG_ENDIAN);
        offset++;

        /* length */
        proto_tree_add_item(st, hf_length, next_tvb, offset, 2, ENC_BIG_ENDIAN);
        offset += 2;

        switch(code)
        {
        case BTOBEX_CODE_VALS_CONNECT:
            proto_tree_add_item(st, hf_version, next_tvb, offset, 1, ENC_BIG_ENDIAN);
            offset++;

            proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, ENC_BIG_ENDIAN);
            offset++;

            proto_tree_add_item(st, hf_max_pkt_len, next_tvb, offset, 2, ENC_BIG_ENDIAN);
            offset += 2;
            break;

        case BTOBEX_CODE_VALS_PUT:
        case BTOBEX_CODE_VALS_GET:
            col_append_fstr(pinfo->cinfo, COL_INFO, " %s",  (final_flag == 0x80) ? "final" : "continue");
            break;

        case BTOBEX_CODE_VALS_SET_PATH:
            proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, ENC_BIG_ENDIAN);
            proto_tree_add_item(st, hf_set_path_flags_0, next_tvb, offset, 1, ENC_BIG_ENDIAN);
            proto_tree_add_item(st, hf_set_path_flags_1, next_tvb, offset, 1, ENC_BIG_ENDIAN);
            offset++;

            proto_tree_add_item(st, hf_constants, next_tvb, offset, 1, ENC_BIG_ENDIAN);
            offset++;
            break;

        case BTOBEX_CODE_VALS_DISCONNECT:
        case BTOBEX_CODE_VALS_ABORT:
            break;

        default:
            {
                guint8 response_opcode = last_opcode[(pinfo->p2p_dir + 1) & 0x01];

                if (response_opcode == BTOBEX_CODE_VALS_CONNECT) {
                    proto_tree_add_item(st, hf_version, next_tvb, offset, 1, ENC_BIG_ENDIAN);
                    offset++;

                    proto_tree_add_item(st, hf_flags, next_tvb, offset, 1, ENC_BIG_ENDIAN);
                    offset++;

                    proto_tree_add_item(st, hf_max_pkt_len, next_tvb, offset, 2, ENC_BIG_ENDIAN);
                    offset += 2;
                }
            }
            break;
        }

        dissect_headers(st, next_tvb, offset, pinfo);
    }
    else
    {
        /* packet fragment */
        col_add_fstr(pinfo->cinfo, COL_INFO, "%s Obex fragment",
                     (pinfo->p2p_dir==P2P_DIR_SENT) ? "Sent" : "Rcvd");

        call_dissector(data_handle, next_tvb, pinfo, tree);
    }

    pinfo->fragmented = save_fragmented;
}
Esempio n. 2
0
static gboolean
dissect_dcc(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree      *dcc_tree, *dcc_optree, *dcc_opnumtree, *ti;
	proto_tree *dcc_tracetree;
	proto_item *hidden_item;
	int offset = 0;
	int client_is_le = 0;
	int op = 0;
	int i, is_response;

	if (pinfo->srcport != DCC_PORT && pinfo->destport != DCC_PORT) {
		/* Not the right port - not a DCC packet. */
		return FALSE;
	}

	/* get at least a full packet structure */
	if ( tvb_length(tvb) < sizeof(DCC_HDR) ) {
		/* Doesn't have enough bytes to contain packet header. */
		return FALSE;
	}

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

	offset = 0;
	is_response = pinfo->srcport == DCC_PORT;

	if (check_col(pinfo->cinfo, COL_INFO)) {
		col_add_fstr(pinfo->cinfo, COL_INFO,
			"%s: %s",
			is_response ? "Response" : "Request",
			val_to_str(tvb_get_guint8(tvb, offset+3),
				 dcc_op_vals, "Unknown Op: %u")
		);
	}

	if (tree) {
		ti = proto_tree_add_item(tree, proto_dcc, tvb, offset, -1,
			FALSE);
		dcc_tree = proto_item_add_subtree(ti, ett_dcc);

		proto_tree_add_item(dcc_tree, hf_dcc_len, tvb,
			offset, 2, FALSE);

		if ( tvb_length(tvb) < tvb_get_ntohs(tvb, offset)) {
			/* Doesn't have number of bytes that header claims. */
			proto_tree_add_text(dcc_tree, tvb, offset, 2, "Error - packet is shorter than header claims!");
		}
		offset += 2;

		proto_tree_add_item(dcc_tree, hf_dcc_pkt_vers, tvb,
			offset, 1, FALSE);
		offset += 1;

		op = tvb_get_guint8(tvb, offset);
		proto_tree_add_item(dcc_tree, hf_dcc_op, tvb,
			offset, 1, FALSE);
		offset += 1;

		proto_tree_add_item(dcc_tree, hf_dcc_clientid, tvb,
			offset, 4, FALSE);
		offset += 4;

		ti = proto_tree_add_text(dcc_tree, tvb, offset, -1, "Operation Numbers (Opaque to Server)");
		dcc_opnumtree = proto_item_add_subtree(ti, ett_dcc_opnums);

		/* Note - these are indeterminate - they are sortof considered opaque to the client */
		/* Make some attempt to figure out if this data is little endian, not guaranteed to be
		correct if connection went through a firewall or similar. */

		/* Very hokey check - if all three of pid/report/retrans look like little-endian
			numbers, host is probably little endian. Probably innacurate on super-heavily-used
			DCC clients though. This should be good enough for now. */
		client_is_le = ( (tvb_get_guint8(tvb, offset+4) | tvb_get_guint8(tvb, offset+4)) &&
						 (tvb_get_guint8(tvb, offset+8) | tvb_get_guint8(tvb, offset+9)) &&
						 (tvb_get_guint8(tvb, offset+12) | tvb_get_guint8(tvb, offset+13)) );

		proto_tree_add_item(dcc_opnumtree, hf_dcc_opnums_host, tvb,
			offset, 4, client_is_le);
		offset += 4;

		proto_tree_add_item(dcc_opnumtree, hf_dcc_opnums_pid, tvb,
			offset, 4, client_is_le);
		offset += 4;

		proto_tree_add_item(dcc_opnumtree, hf_dcc_opnums_report, tvb,
			offset, 4, client_is_le);
		offset += 4;

		proto_tree_add_item(dcc_opnumtree, hf_dcc_opnums_retrans, tvb,
			offset, 4, client_is_le);
		offset += 4;

		ti = proto_tree_add_text(dcc_tree, tvb, offset, -1, "Operation: %s",
			val_to_str(op, dcc_op_vals, "Unknown Op: %u"));
		dcc_optree = proto_item_add_subtree(ti, ett_dcc_op);

		switch(op) {
			case DCC_OP_NOP:
				D_SIGNATURE();
				break;

			case DCC_OP_REPORT:
				D_TARGET();
				for (i=0; i<=DCC_QUERY_MAX &&
					tvb_bytes_exist(tvb, offset+sizeof(DCC_SIGNATURE),1); i++)
				{
					D_CHECKSUM();
				}
				D_SIGNATURE();
				break;

			case DCC_OP_QUERY_RESP:
				for (i=0; i<=DCC_QUERY_MAX &&
					tvb_bytes_exist(tvb, offset+sizeof(DCC_SIGNATURE),1); i++)
				{
					D_TARGET();
				}
				D_SIGNATURE();
				break;

			case DCC_OP_ADMN:
				if ( is_response )
				{
					int left_local = tvb_length_remaining(tvb, offset) -
						sizeof(DCC_SIGNATURE);
					if ( left_local == sizeof(DCC_ADMN_RESP_CLIENTS) )
					{
						D_LABEL("Addr", 16);
						D_LABEL("Id", sizeof(DCC_CLNT_ID));
						D_LABEL("Last Used", 4);
						D_LABEL("Requests", 4);
					}
					else
					{
						D_TEXT("Response Text", sizeof(DCC_SIGNATURE));
					}
					D_SIGNATURE();
				}
				else
				{
					int aop;

					D_DATE();

					aop = tvb_get_guint8(tvb, offset+4);
					proto_tree_add_item(dcc_optree, hf_dcc_adminop, tvb, offset+4,
						1, FALSE);
					if (check_col(pinfo->cinfo, COL_INFO)) {
						col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
							val_to_str(tvb_get_guint8(tvb,offset+4),
							dcc_adminop_vals, "Unknown (%u)"));
					}

					if (aop == DCC_AOP_TRACE_ON || aop == DCC_AOP_TRACE_OFF )
					{
						ti = proto_tree_add_item(dcc_optree, hf_dcc_trace, tvb, offset,
							4, FALSE);
						dcc_tracetree = proto_item_add_subtree(ti, ett_dcc_trace);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_admin, tvb, offset, 4, FALSE);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_anon, tvb, offset, 4, FALSE);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_client, tvb, offset, 4, FALSE);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_rlim, tvb, offset, 4, FALSE);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_query, tvb, offset, 4, FALSE);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_ridc, tvb, offset, 4, FALSE);
						proto_tree_add_item(dcc_tracetree, hf_dcc_trace_flood, tvb, offset, 4, FALSE);
					}
					else if ( aop == DCC_AOP_FLOD )
					{
						proto_tree_add_item(dcc_optree, hf_dcc_floodop,
							tvb, offset, 4, FALSE);
						if (check_col(pinfo->cinfo, COL_INFO)) {
							col_append_fstr(pinfo->cinfo, COL_INFO, ", %s",
								val_to_str(tvb_get_ntohl(tvb,offset),
								dcc_floodop_vals, "Unknown (%u)"));
						}
					}
					else
					{
						proto_tree_add_item(dcc_optree, hf_dcc_adminval,
							tvb, offset, 4, FALSE);
					}
					offset += 4;

					offset += 1; /* admin op we did in reverse order */
					D_LABEL("Pad", 3);
					D_SIGNATURE();
				}
				break;

			case DCC_OP_OK:
				proto_tree_add_item(dcc_optree, hf_dcc_max_pkt_vers, tvb,
					offset, 1, FALSE);
				offset += 1;

				D_LABEL("Unused", 1);

				proto_tree_add_item(dcc_optree, hf_dcc_qdelay_ms, tvb,
					offset, 2, FALSE);
				offset += 2;

				proto_tree_add_item(dcc_optree, hf_dcc_brand, tvb,
					offset, sizeof(DCC_BRAND), FALSE);
				offset += sizeof(DCC_BRAND);

				D_SIGNATURE();
				break;

			default:
				/* do nothing */
				break;
		}
	}

	return TRUE;
}
Esempio n. 3
0
static int dissect_InitiatingMessageValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  return (dissector_try_uint(sbc_ap_proc_imsg_dissector_table, ProcedureCode, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
}
Esempio n. 4
0
/*
 * dissect_pgm - The dissector for Pragmatic General Multicast
 */
static void
dissect_pgm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint16 pgmhdr_sport;
	guint16 pgmhdr_dport;
	guint8 pgmhdr_type;
	guint8 pgmhdr_opts;
	guint16 pgmhdr_cksum;
	guint16 pgmhdr_tsdulen;
	guint32 sqn;
	guint16 afi;

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

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

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

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

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

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

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

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

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

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

		pgm_tree = proto_item_add_subtree(ti, ett_pgm);

		cursor = ptvcursor_new(pgm_tree, tvb, 0);

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

		if (isdata)
			decode_pgm_ports(tvb, ptvcursor_current_offset(cursor), pinfo, tree, pgmhdr_sport, pgmhdr_dport);
	}
}
Esempio n. 5
0
static void
dissect_gmr1_dtap(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	guint32 len, offset;
	gmr1_msg_func_t msg_func;
	const gchar *msg_str;
	gint ett_tree;
	int hf_idx;
	proto_item *dtap_item = NULL/*, *pd_item = NULL*/;
	proto_tree *dtap_tree = NULL/*, *pd_tree = NULL*/;
	guint32 oct[2];
	guint8 pd;

	/* Scan init */
	len = tvb_length(tvb);
	offset = 0;

	/* Protocol descriptor */
	oct[0] = tvb_get_guint8(tvb, offset++);

	if ((oct[0] & GMR1_PD_EXT_MSK) == GMR1_PD_EXT_VAL)
		pd = oct[0] & 0xff;
	else
		pd = oct[0] & 0x0f;

	/* HACK: Quick delegation hack to GSM */
	if (pd != GMR1_PD_RR) {
		call_dissector(gsm_dtap_handle, tvb, pinfo, tree);
		return;
	}

	/* Fill up some info */
	col_append_str(pinfo->cinfo, COL_INFO, " (DTAP) ");

	col_append_fstr(pinfo->cinfo, COL_INFO, "(%s) ",
		val_to_str(pd, gmr1_pd_short_vals, "Unknown (%u)"));

	/* Get message parameters */
	oct[1] = tvb_get_guint8(tvb, offset);

	gmr1_get_msg_params((gmr1_pd_e)pd, oct[1], &msg_str, &ett_tree, &hf_idx, &msg_func);

	/* Create protocol tree */
	if (msg_str == NULL)
	{
		dtap_item = proto_tree_add_protocol_format(
			tree, proto_gmr1_dtap, tvb, 0, len,
			"GMR-1 DTAP - Message Type (0x%02x)", oct[1]);
		dtap_tree = proto_item_add_subtree(dtap_item, ett_gmr1_dtap);

		col_append_fstr(pinfo->cinfo, COL_INFO, "Message Type (0x%02x) ", oct[1]);
	}
	else
	{
		dtap_item = proto_tree_add_protocol_format(
			tree, proto_gmr1_dtap, tvb, 0, -1,
			"GMR-1 DTAP - %s", msg_str);
		dtap_tree = proto_item_add_subtree(dtap_item, ett_gmr1_dtap);

		col_append_fstr(pinfo->cinfo, COL_INFO, "%s ", msg_str);
	}

	/* Start over */
	offset = 0;

	/* Protocol discriminator item */
	/*pd_item =*/ proto_tree_add_text(
		dtap_tree, tvb, 1, 1,
		"Protocol Discriminator: %s",
		val_to_str(pd, gmr1_pd_vals, "Unknown (%u)")
	);

	/*pd_tree = proto_item_add_subtree(pd_item, ett_gmr1_pd);*/

		/* Move on */
	offset++;

	/* Message type - [1] 11.4 */
	proto_tree_add_uint_format(
		dtap_tree, hf_idx, tvb, offset, 1, oct[1],
		"Message Type: %s", msg_str ? msg_str : "(Unknown)"
	);

	offset++;

	/* Decode elements */
	if (msg_func) {
		(*msg_func)(tvb, dtap_tree, pinfo, offset, len - offset);
	} else {
		proto_tree_add_text(dtap_tree, tvb, offset, len - offset,
		                    "Message Elements");
	}

	/* Done ! */
	return;
}
Esempio n. 6
0
static int
dissect_skype_udp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item *ti;
	proto_tree *skype_tree = NULL;
	guint32 offset = 0;
	guint32 packet_length;
	guint8 packet_type, packet_unk;

	conversation_t   *conversation = NULL;
	skype_udp_conv_info_t *skype_udp_info;

	/* look up the conversation */
	conversation = find_or_create_conversation(pinfo);

	/* if conversation found get the data pointer that you stored */
	skype_udp_info = conversation_get_proto_data(conversation, proto_skype);
	if (!skype_udp_info) {
		/* new conversation create local data structure */
		skype_udp_info = se_alloc(sizeof(skype_udp_conv_info_t));
		skype_udp_info->global_src_ip = 0;
		skype_udp_info->global_dst_ip = 0;
		conversation_add_proto_data(conversation, proto_skype,
			skype_udp_info);
	}
	/* at this point the conversation data is ready */

	packet_type = tvb_get_guint8(tvb, 2) & SKYPE_SOM_TYPE_MASK;
	packet_unk = (tvb_get_guint8(tvb, 2) & SKYPE_SOM_UNK_MASK) >> 4;

	packet_length = tvb_length(tvb);

	col_set_str(pinfo->cinfo, COL_PROTOCOL, PROTO_SHORT_NAME);
	col_add_str(pinfo->cinfo, COL_INFO, val_to_str(packet_type,
		skype_type_vals, "Type 0x%1x"));
	if (packet_unk) {
		col_append_fstr(pinfo->cinfo, COL_INFO, " Unk: %1x", packet_unk);
	}

	if (tree) {
		/* Start of message dissection */
		ti = proto_tree_add_item(tree, proto_skype, tvb, offset, -1,
		    ENC_NA);
		skype_tree = proto_item_add_subtree(ti, ett_skype);

		proto_tree_add_item(skype_tree, hf_skype_som_id, tvb, offset, 2,
			ENC_BIG_ENDIAN);
		offset += 2;
		proto_tree_add_item(skype_tree, hf_skype_som_unk, tvb, offset, 1,
			ENC_NA);
		proto_tree_add_item(skype_tree, hf_skype_som_type, tvb, offset, 1,
			ENC_NA);
		offset += 1;

		/* Body dissection */
		switch (packet_type) {

		case SKYPE_TYPE_UNKNOWN_0:
			proto_tree_add_item(skype_tree, hf_skype_unknown_0_unk1, tvb, offset, -1,
				ENC_NA);
			offset = packet_length;
			break;
		case SKYPE_TYPE_PAYLOAD:
			proto_tree_add_item(skype_tree, hf_skype_payload_iv, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_payload_crc, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_payload_enc_data, tvb, offset, -1,
				ENC_NA);
			offset = packet_length;
			break;
		case SKYPE_TYPE_FFR:
			proto_tree_add_item(skype_tree, hf_skype_ffr_num, tvb, offset, 1,
				ENC_NA);
			offset += 1;
			proto_tree_add_item(skype_tree, hf_skype_ffr_unk1, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_ffr_iv, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_ffr_crc, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_ffr_enc_data, tvb, offset, -1,
				ENC_NA);
			offset = packet_length;
			break;
		case SKYPE_TYPE_NAT_INFO:
			proto_tree_add_item(skype_tree, hf_skype_natinfo_srcip, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			skype_udp_info->global_src_ip = tvb_get_ipv4(tvb, offset);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_natinfo_dstip, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			skype_udp_info->global_dst_ip = tvb_get_ipv4(tvb, offset);
			offset += 4;
			break;
		case SKYPE_TYPE_NAT_REPEAT:
			proto_tree_add_item(skype_tree, hf_skype_natrequest_srcip, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			skype_udp_info->global_src_ip = tvb_get_ipv4(tvb, offset);
			offset += 4;
			proto_tree_add_item(skype_tree, hf_skype_natrequest_dstip, tvb, offset, 4,
				ENC_BIG_ENDIAN);
			skype_udp_info->global_dst_ip = tvb_get_ipv4(tvb, offset);
			offset += 4;
			break;
		case SKYPE_TYPE_AUDIO:
			proto_tree_add_item(skype_tree, hf_skype_audio_unk1, tvb, offset, -1,
				ENC_NA);
			offset = packet_length;
			break;
		case SKYPE_TYPE_UNKNOWN_F:
			proto_tree_add_item(skype_tree, hf_skype_unknown_f_unk1, tvb, offset, -1,
				ENC_NA);
			offset = packet_length;
			break;
		default:
			proto_tree_add_item(skype_tree, hf_skype_unknown_packet, tvb, offset, -1,
				ENC_NA);
			offset = packet_length;
			break;
		}
	}
	return offset;
}
Esempio n. 7
0
static void
dissect_pop(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  struct pop_proto_data  *frame_data_p;
  gboolean               is_request;
  gboolean               is_continuation;
  proto_tree             *pop_tree, *reqresp_tree;
  proto_item             *ti;
  gint                   offset = 0;
  const guchar           *line;
  gint                   next_offset;
  int                    linelen;
  int                    tokenlen;
  const guchar           *next_token;
  fragment_data          *frag_msg = NULL;
  tvbuff_t               *next_tvb = NULL;
  conversation_t         *conversation = NULL;
  struct pop_data_val    *data_val = NULL;
  gint                   length_remaining;

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

  /*
   * Find the end of the first line.
   *
   * Note that "tvb_find_line_end()" will return a value that is
   * not longer than what's in the buffer, so the "tvb_get_ptr()"
   * call won't throw an exception.
   */
  linelen = tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);
  line = tvb_get_ptr(tvb, offset, linelen);

  if (pinfo->match_uint == pinfo->destport) {
    is_request = TRUE;
    is_continuation = FALSE;
  } else {
    is_request = FALSE;
    is_continuation = response_is_continuation(line);
  }

  frame_data_p = p_get_proto_data(pinfo->fd, proto_pop);

  if (!frame_data_p) {

    conversation = find_or_create_conversation(pinfo);

    data_val = conversation_get_proto_data(conversation, proto_pop);

    if (!data_val) {

      /*
       * No - create one and attach it.
       */
      data_val = se_alloc0(sizeof(struct pop_data_val));

      conversation_add_proto_data(conversation, proto_pop, data_val);
    }
  }

  if (check_col(pinfo->cinfo, COL_INFO)) {
    /*
     * Put the first line from the buffer into the summary
     * if it's a POP request or reply (but leave out the
     * line terminator).
     * Otherwise, just call it a continuation.
     */
    if (is_continuation) {
      length_remaining = tvb_length_remaining(tvb, offset);
      col_add_fstr(pinfo->cinfo, COL_INFO, "S: DATA fragment, %d byte%s",
                   length_remaining, plurality (length_remaining, "", "s"));
    }
    else
      col_add_fstr(pinfo->cinfo, COL_INFO, "%s: %s", is_request ? "C" : "S",
                   format_text(line, linelen));
  }

  ti = proto_tree_add_item(tree, proto_pop, tvb, offset, -1, ENC_NA);
  pop_tree = proto_item_add_subtree(ti, ett_pop);

  if (is_continuation) {

    if (pop_data_desegment) {

      if (!frame_data_p) {

        data_val->msg_read_len += tvb_length(tvb);

        frame_data_p = se_alloc(sizeof(struct pop_proto_data));

        frame_data_p->conversation_id = conversation->index;
        frame_data_p->more_frags = data_val->msg_read_len < data_val->msg_tot_len;

        p_add_proto_data(pinfo->fd, proto_pop, frame_data_p);
      }

      frag_msg = fragment_add_seq_next(tvb, 0, pinfo,
                                       frame_data_p->conversation_id,
                                       pop_data_segment_table,
                                       pop_data_reassembled_table,
                                       tvb_length(tvb),
                                       frame_data_p->more_frags);

      next_tvb = process_reassembled_data(tvb, offset, pinfo,
                                          "Reassembled DATA",
                                          frag_msg, &pop_data_frag_items,
                                          NULL, pop_tree);

      if (next_tvb) {

        if (imf_handle)
          call_dissector(imf_handle, next_tvb, pinfo, tree);

        if (data_val) {
          /* we have read everything - reset */

          data_val->msg_read_len = 0;
          data_val->msg_tot_len = 0;
        }
        pinfo->fragmented = FALSE;
      } else {
        pinfo->fragmented = TRUE;
      }

    } else {

      /*
       * Put the whole packet into the tree as data.
       */
      call_dissector(data_handle,tvb, pinfo, pop_tree);

    }
    return;
  }

  /*
   * Put the line into the protocol tree.
   */
  ti = proto_tree_add_string_format(pop_tree,
                                    (is_request) ?
                                        hf_pop_request :
                                        hf_pop_response,
                                    tvb, offset,
                                    next_offset - offset,
                                    "", "%s",
                                    tvb_format_text(tvb, offset, next_offset - offset));
  reqresp_tree = proto_item_add_subtree(ti, ett_pop_reqresp);

  /*
   * Extract the first token, and, if there is a first
   * token, add it as the request or reply code.
   */
  tokenlen = get_token_len(line, line + linelen, &next_token);
  if (tokenlen != 0) {
    proto_tree_add_item(reqresp_tree,
                        (is_request) ?
                            hf_pop_request_command :
                            hf_pop_response_indicator,
                        tvb, offset, tokenlen, ENC_ASCII|ENC_NA);

    if (data_val) {
      if (is_request) {
        /* see if this is RETR or TOP command */
        if (g_ascii_strncasecmp(line, "RETR", 4) == 0 ||
           g_ascii_strncasecmp(line, "TOP", 3) == 0)
          /* the next response will tell us how many bytes */
          data_val->msg_request = TRUE;
      } else {
        if (data_val->msg_request) {
          /* this is a response to a RETR or TOP command */

          if (g_ascii_strncasecmp(line, "+OK ", 4) == 0) {
            /* the message will be sent - work out how many bytes */
            data_val->msg_read_len = 0;
            data_val->msg_tot_len = atoi(line + 4);
          }
          data_val->msg_request = FALSE;
        }
      }
    }

    offset += (gint) (next_token - line);
    linelen -= (int) (next_token - line);
  }


  if (tree) {
    /*
     * Add the rest of the first line as request or
     * reply param/description.
     */
    if (linelen != 0) {
      proto_tree_add_item(reqresp_tree,
                          (is_request) ?
                              hf_pop_request_parameter :
                              hf_pop_response_description,
                          tvb, offset, linelen, ENC_ASCII|ENC_NA);
    }
    offset = next_offset;

    /*
     * Show the rest of the request or response as text,
     * a line at a time.
     */
    while (tvb_offset_exists(tvb, offset)) {
      /*
       * Find the end of the line.
       */
      tvb_find_line_end(tvb, offset, -1, &next_offset, FALSE);

      /*
       * Put this line.
       */
      proto_tree_add_string_format(pop_tree,
                                   (is_request) ?
                                       hf_pop_request_data :
                                       hf_pop_response_data,
                                   tvb, offset,
                                   next_offset - offset,
                                   "", "%s",
                                   tvb_format_text(tvb, offset, next_offset - offset));
      offset = next_offset;
    }
  }
}
Esempio n. 8
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, FALSE);
    pim_tree = proto_item_add_subtree(ti, ett_pim);

    proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, FALSE);
    proto_tree_add_item(pim_tree, hf_pim_type, tvb, offset, 1, FALSE);
    proto_tree_add_item(pim_tree, hf_pim_res_bytes, tvb, offset + 1, 1, FALSE);
    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, FALSE);
            proto_tree_add_item(opt_tree, hf_pim_optionlength, tvb, offset + 2, 2, FALSE);

            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, FALSE);
                proto_tree_add_item(opt_tree, hf_pim_propagation_delay, tvb, offset + 4, 2, FALSE);
                proto_tree_add_item(opt_tree, hf_pim_override_interval, tvb, offset + 6, 2, FALSE);
                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, FALSE);
                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, FALSE);
                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, FALSE);
                proto_tree_add_item(opt_tree, hf_pim_state_refresh_interval, tvb, offset + 5, 1, FALSE);
                proto_tree_add_item(opt_tree, hf_pim_state_refresh_reserved, tvb, offset + 6, 2, FALSE);
                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, FALSE);
                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, FALSE);
        offset += 1;    /* skip reserved field */

        ngroup = tvb_get_guint8(tvb, offset);
        proto_tree_add_item(pimopt_tree, hf_pim_numgroups, tvb, offset, 1, FALSE);
        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, FALSE);
            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, FALSE);
            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, FALSE);
        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, FALSE);
        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, FALSE);
        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, FALSE);
        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:;
}
static void
dissect_gsm_um(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_tree *gsm_um_tree = NULL;
	proto_item *ti;

	col_set_str(pinfo->cinfo, COL_PROTOCOL, "GSM Um");

	if (pinfo->pseudo_header->gsm_um.uplink) {
		col_set_str(pinfo->cinfo, COL_RES_DL_DST, "BTS");
		col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "MS");
	}
	else {
		switch (pinfo->pseudo_header->gsm_um.channel) {
			case GSM_UM_CHANNEL_BCCH:
			case GSM_UM_CHANNEL_CCCH:
			case GSM_UM_CHANNEL_PCH:
			case GSM_UM_CHANNEL_AGCH:
				col_set_str(pinfo->cinfo, COL_RES_DL_DST, "Broadcast");
				break;
			default:
				col_set_str(pinfo->cinfo, COL_RES_DL_DST, "MS");
				break;
		}
		col_set_str(pinfo->cinfo, COL_RES_DL_SRC, "BTS");
	}

	if (tree) {
		const char *channel;

		ti = proto_tree_add_item(tree, proto_gsm_um, tvb, 0, 0, ENC_NA);
		gsm_um_tree = proto_item_add_subtree(ti, ett_gsm_um);

		switch( pinfo->pseudo_header->gsm_um.channel ) {
			case GSM_UM_CHANNEL_BCCH: channel = "BCCH"; break;
			case GSM_UM_CHANNEL_CCCH: channel = "CCCH"; break;
			case GSM_UM_CHANNEL_PCH: channel = "PCH"; break;
			case GSM_UM_CHANNEL_AGCH: channel = "AGCH"; break;
			case GSM_UM_CHANNEL_SACCH: channel = "SACCH"; break;
			case GSM_UM_CHANNEL_FACCH: channel = "FACCH"; break;
			case GSM_UM_CHANNEL_SDCCH: channel = "SDCCH"; break;
			default: channel = "Unknown"; break;
		}

		if( pinfo->pseudo_header->gsm_um.uplink ) {
			proto_tree_add_string(gsm_um_tree, hf_gsm_um_direction, tvb, 0, 0, "Uplink");
		}
		else {
			proto_tree_add_string(gsm_um_tree, hf_gsm_um_direction, tvb, 0, 0, "Downlink");
		}

		proto_tree_add_string(gsm_um_tree, hf_gsm_um_channel, tvb, 0, 0, channel);

		/* Show the other fields, if we have them (ie. downlink, BTS->MS) */
		if( !pinfo->pseudo_header->gsm_um.uplink ) {
			const char *band;
			guint downlink, uplink;

			decode_arfcn(pinfo->pseudo_header->gsm_um.arfcn, &band, &uplink, &downlink);

			proto_tree_add_uint(gsm_um_tree, hf_gsm_um_arfcn, tvb, 0, 0,
				pinfo->pseudo_header->gsm_um.arfcn);
			proto_tree_add_string(gsm_um_tree, hf_gsm_um_band, tvb, 0, 0,
				band);
			proto_tree_add_uint_format_value(gsm_um_tree, hf_gsm_um_frequency, tvb, 0, 0,
				downlink, "%u.%03uMHz", downlink / 1000, downlink % 1000);
			proto_tree_add_uint(gsm_um_tree, hf_gsm_um_bsic, tvb, 0, 0,
				pinfo->pseudo_header->gsm_um.bsic);
			proto_tree_add_uint(gsm_um_tree, hf_gsm_um_frame, tvb, 0, 0,
				pinfo->pseudo_header->gsm_um.tdma_frame);
			proto_tree_add_uint(gsm_um_tree, hf_gsm_um_error, tvb, 0, 0,
				pinfo->pseudo_header->gsm_um.error);
			proto_tree_add_uint(gsm_um_tree, hf_gsm_um_timeshift, tvb, 0, 0,
				pinfo->pseudo_header->gsm_um.timeshift);
		}
	}

	/* TODO: If CCCH downlink could work out of PCH or AGCH by peeking at next bytes, uplink is RACH */

	switch( pinfo->pseudo_header->gsm_um.channel ) {
		case GSM_UM_CHANNEL_BCCH:
		case GSM_UM_CHANNEL_CCCH:
		case GSM_UM_CHANNEL_PCH:
		case GSM_UM_CHANNEL_AGCH:
			if( !pinfo->pseudo_header->gsm_um.uplink ) {
				tvbuff_t *next_tvb;
				guint8 pseudo_len, len_left, len_byte;

				len_left = tvb_length(tvb);
				len_byte = tvb_get_guint8(tvb, 0);
				pseudo_len = len_byte >> 2;
				next_tvb = tvb_new_subset(tvb, 1, MIN(len_left, pseudo_len), -1);

				if (tree) {
					proto_tree_add_uint(gsm_um_tree, hf_gsm_um_l2_pseudo_len, tvb, 0, 1,
						len_byte);
				}

				/* Only dissect non-empty frames */
				if( tvb_length(next_tvb) ) {
					call_dissector(dtap_handle, next_tvb, pinfo, tree);
				}
			}
			else {
Esempio n. 10
0
static int
dissect_text_lines(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data)
{
	proto_tree	*subtree;
	proto_item	*ti;
	gint		offset = 0, next_offset;
	gint		len;
	const char	*data_name;
	int length = tvb_length(tvb);

	/* Check if this is actually xml
	 * If there is less than 38 characters this is not XML
	 * <?xml version="1.0" encoding="UTF-8"?>
	 */
	if(length > 38){
		if (tvb_strncaseeql(tvb, 0, "<?xml", 5) == 0){
			call_dissector(xml_handle, tvb, pinfo, tree);
			return tvb_length(tvb);
		}
	}

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

	if (data_name)
		col_append_sep_fstr(pinfo->cinfo, COL_INFO, " ", "(%s)",
				data_name);

	if (tree) {
		ti = proto_tree_add_item(tree, proto_text_lines,
				tvb, 0, -1, ENC_NA);
		if (data_name)
			proto_item_append_text(ti, ": %s", data_name);
		subtree = proto_item_add_subtree(ti, ett_text_lines);
		/* Read the media line by line */
		while (tvb_reported_length_remaining(tvb, offset) != 0) {
			/*
			 * XXX - we need to be passed the parameters
			 * of the content type via "pinfo->private_data",
			 * so that we know the character set.  We'd
			 * have to handle that character set, which
			 * might be a multibyte character set such
			 * as "iso-10646-ucs-2", or might require other
			 * special processing.
			 */
			len = tvb_find_line_end(tvb, offset,
					tvb_ensure_length_remaining(tvb, offset),
					&next_offset, FALSE);
			if (len == -1)
				break;

			/* We use next_offset - offset instead of len in the
			 * call to tvb_format_text() so it will include the
			 * line terminator(s) (\r and/or \n) in the display.
			 */
			proto_tree_add_text(subtree, tvb, offset, next_offset - offset,
					    "%s", tvb_format_text(tvb, offset,
								  next_offset - offset));
			offset = next_offset;
		}
	}

	return tvb_length(tvb);
}
Esempio n. 11
0
/* This function is only called from the IGMP dissector */
int
dissect_pimv1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
              int offset) {
    guint8 pim_type;
    guint8 pim_ver;
    guint length, pim_length;
    guint16 pim_cksum, computed_cksum;
    vec_t cksum_vec[1];
    proto_tree *pim_tree = NULL;
    proto_item *ti;
    proto_tree *pimopt_tree = NULL;
    proto_item *tiopt;

    if (!proto_is_protocol_enabled(find_protocol_by_id(proto_pim))) {
        /*
         * We are not enabled; skip entire packet to be nice to the
         * IGMP layer (so clicking on IGMP will display the data).
         */
        return offset+tvb_length_remaining(tvb, offset);
    }

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

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

    /* Put IGMP type, 0x14, into the tree */
    proto_tree_add_text(pim_tree, tvb, offset, 1,
                        "Type: PIM (0x14)");
    offset += 1;

    pim_type = tvb_get_guint8(tvb, offset);
    if (check_col(pinfo->cinfo, COL_INFO))
        col_add_str(pinfo->cinfo, COL_INFO,
                    val_to_str(pim_type, type1vals, "Unknown (%u)"));

    proto_tree_add_uint(pim_tree, hf_pim_code, tvb, offset, 1, pim_type);
    offset += 1;

    pim_cksum = tvb_get_ntohs(tvb, offset);
    pim_ver = PIM_VER(tvb_get_guint8(tvb, offset + 2));
    if (pim_ver != 1) {
        /*
         * Not PIMv1 - what gives?
         */
        proto_tree_add_uint(pim_tree, hf_pim_cksum, tvb,
                            offset, 2, pim_cksum);

        offset += 2;
        proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, FALSE);
        return offset+tvb_length_remaining(tvb, offset);
    }

    /*
     * Well, it's PIM v1, 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.
     */
    length = tvb_length(tvb);
    if (pim_type == 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);
    }

    if (!pinfo->fragmented && length >= pim_length) {
        /*
         * The packet isn't part of a fragmented datagram and isn't
         * truncated, so we can checksum it.
         */
        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);
        if (computed_cksum == 0) {
            proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
                                       offset, 2, pim_cksum,
                                       "Checksum: 0x%04x [correct]",
                                       pim_cksum);
        } else {
            proto_tree_add_uint_format(pim_tree, hf_pim_cksum, tvb,
                                       offset, 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, pim_cksum);
    }
    offset += 2;

    proto_tree_add_item(pim_tree, hf_pim_version, tvb, offset, 1, FALSE);
    offset += 1;

    offset += 3;        /* skip reserved stuff */

    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;

    /* version 1 decoder */
    switch (pim_type) {
    case 0:     /* query */
    {
        guint16 holdtime;

        proto_tree_add_item(pimopt_tree, hf_pim_mode, tvb, offset, 1, FALSE);
        offset += 2;

        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;
        break;
    }

    case 1:     /* register */
    {
        guint8 v_hl;
        tvbuff_t *next_tvb;

        /*
         * 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));
            } 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 */
    {
        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Group: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;
        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Source: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;
        break;
    }

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

        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Upstream-neighbor: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;

        offset += 2;    /* skip reserved stuff */

        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;

        offset += 1;    /* skip reserved stuff */

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

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

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

        for (i = 0; i < ngroup; i++) {
            /*
             * XXX - does the group address have the length "adr_len"
             * and the group mask the length "mask_len"?
             */
            tigroup = proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                                          "Group %d: %s", i,
                                          tvb_ip_to_str(tvb, offset));
            grouptree = proto_item_add_subtree(tigroup, ett_pim);
            offset += 4;

            proto_tree_add_text(grouptree, tvb, offset, 4,
                                "Group %d Mask: %s", i,
                                tvb_ip_to_str(tvb, offset));
            offset += 4;

            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, FALSE);
            subtree = proto_item_add_subtree(tisub, ett_pim);
            off = offset + 4;
            for (j = 0; j < njoin; j++) {
                s = dissect_pimv1_addr(tvb, off);
                proto_tree_add_text(subtree, tvb, off, 6,
                                    "IP address: %s", s);
                off += 6;
            }

            tisub = proto_tree_add_item(grouptree, hf_pim_numprunes, tvb,
                                        offset + 2, 2, FALSE);
            subtree = proto_item_add_subtree(tisub, ett_pim);
            for (j = 0; j < nprune; j++) {
                s = dissect_pimv1_addr(tvb, off);
                proto_tree_add_text(subtree, tvb, off, 6,
                                    "IP address: %s", s);
                off += 6;
            }
            offset = off;
        }
        break;
    }

    case 4:     /* rp-reachability */
    {
        guint16 holdtime;

        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Group Address: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;

        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Group Mask: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;

        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "RP Address: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;

        offset += 2;    /* skip reserved stuff */

        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;
        break;
    }

    case 5:     /* assert */
    {
        guint32 pref;

        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Group Address: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;

        proto_tree_add_text(pimopt_tree, tvb, offset, 4,
                            "Group Mask: %s",
                            tvb_ip_to_str(tvb, offset));
        offset += 4;

        proto_tree_add_item(pimopt_tree, hf_pim_rpt, tvb, offset, 1, FALSE);
        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, FALSE);
        offset += 4;
        break;
    }

    default:
        break;
    }
done:;

    return offset+tvb_length_remaining(tvb, offset);
}
Esempio n. 12
0
static gboolean
dissect_fcip (tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree,
              gboolean check_port)
{
    gint offset = 0,
         start  = 0,
         frame_len = 0;
    gint bytes_remaining = tvb_length (tvb);
    guint8 pflags, sof = 0, eof = 0;
   /* Set up structures needed to add the protocol subtree and manage it */
    proto_item *ti;
    proto_tree *fcip_tree = NULL;
    tvbuff_t *next_tvb;

    if (bytes_remaining < FCIP_ENCAP_HEADER_LEN) {
        return FALSE;
    }

    if (check_port &&
        ((pinfo->srcport != fcip_port) && (pinfo->destport != fcip_port))) {
        return FALSE;
    }

    while (bytes_remaining > FCIP_ENCAP_HEADER_LEN) {
        if ((offset = get_next_fcip_header_offset (tvb, pinfo, offset)) == -1) {
            return FALSE;
        }
        else if (offset == -2) {
            /* We need more data to desegment */
            return (TRUE);
        }

        start = offset;
        col_set_str(pinfo->cinfo, COL_PROTOCOL, "FCIP");

        frame_len = (tvb_get_ntohs (tvb, offset+12) & 0x03FF)*4;

        if (bytes_remaining < frame_len) {
            if(fcip_desegment && pinfo->can_desegment) {
                /*
                 * This frame doesn't have all of the data for
                 * this message, but we can do reassembly on it.
                 *
                 * Tell the TCP dissector where the data for this
                 * message starts in the data it handed us, and
                 * how many more bytes we need, and return.
                 */
                pinfo->desegment_offset = offset;
                pinfo->desegment_len = frame_len - bytes_remaining;
                return (TRUE);
            }
        }

        pflags = tvb_get_guint8 (tvb, start+8);

        if (tree) {
            if (FCIP_IS_SF (pflags)) {
                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP");
            }
            else if (tvb_bytes_exist (tvb, offset, offset+frame_len-4)) {
                sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);
                eof = tvb_get_guint8 (tvb, offset+frame_len - 4);

                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP (%s/%s)",
                                                     val_to_str (sof, fcip_sof_vals,
                                                                 "0x%x"),
                                                     val_to_str (eof, fcip_eof_vals,
                                                                 "0x%x"));
            }
            else {
                sof = tvb_get_guint8 (tvb, offset+FCIP_ENCAP_HEADER_LEN);

                ti = proto_tree_add_protocol_format (tree, proto_fcip, tvb, 0,
                                                     FCIP_ENCAP_HEADER_LEN,
                                                     "FCIP (%s/%s)",
                                                     val_to_str (sof, fcip_sof_vals,
                                                                 "0x%x"),
                                                     "NA");
            }
            fcip_tree = proto_item_add_subtree (ti, ett_fcip);
            /* Dissect the Common FC Encap header */
            dissect_fcencap_header (tvb, fcip_tree, offset);

            offset += FCIP_ENCAP_HEADER_LEN;

            if (!FCIP_IS_SF (pflags)) {
                /* print SOF */
                proto_tree_add_item (fcip_tree, hf_fcip_sof, tvb, offset, 1, 0);
                proto_tree_add_item (fcip_tree, hf_fcip_sof_c, tvb, offset+2, 1, 0);
                /* print EOF */

                offset += (frame_len-FCIP_ENCAP_HEADER_LEN-4);
                if (tvb_bytes_exist (tvb, offset, 4)) {
                    proto_tree_add_item (fcip_tree, hf_fcip_eof, tvb, offset, 1, 0);
                    proto_tree_add_item (fcip_tree, hf_fcip_eof_c, tvb, offset+2, 1, 0);
                }
            }
        }

        /* Call the FC Dissector if this is carrying an FC frame */
        if (!FCIP_IS_SF(pflags)) {
            /* Set the SOF/EOF flags in the packet_info header */
            pinfo->sof_eof = 0;

            if (sof) {
                if ((sof == FCIP_SOFi3) || (sof == FCIP_SOFi2) || (sof == FCIP_SOFi4)) {
                    pinfo->sof_eof = PINFO_SOF_FIRST_FRAME;
                }
                else if (sof == FCIP_SOFf) {
                    pinfo->sof_eof = PINFO_SOF_SOFF;
                }

                if (eof != FCIP_EOFn) {
                    pinfo->sof_eof |= PINFO_EOF_LAST_FRAME;
                }
                else if (eof != FCIP_EOFt) {
                    pinfo->sof_eof |= PINFO_EOF_INVALID;
                }
            }

            /* Special frame bit is not set */
            next_tvb = tvb_new_subset_remaining (tvb, FCIP_ENCAP_HEADER_LEN+4);
            if (fc_handle) {
                call_dissector (fc_handle, next_tvb, pinfo, tree);
            }
            else if (data_handle) {
                call_dissector (data_handle, next_tvb, pinfo, tree);
            }
        }
        else {
            col_set_str(pinfo->cinfo, COL_INFO, "Special Frame");
            if (FCIP_IS_CH (pflags)) {
                col_append_str(pinfo->cinfo, COL_INFO, "(Changed)");
            }

            dissect_fcip_sf (tvb, fcip_tree, offset+4);
        }

        bytes_remaining -= frame_len;
    }

    return (TRUE);
}
Esempio n. 13
0
/* XXX: Are all the tests against tvb_length() really the right way to handle invalid fields ?
 *      It seems to me that invalid fields should just add an expert item
 *        or cause a "Malformed" exception.
 */
static void
dissect_elcom(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
        gboolean    is_request, length_ok;
        proto_tree *elcom_tree;
        proto_item *ti, *hidden_item;
        gint        offset = 0;
        guint       elcom_len;
        guint8      elcom_msg_type;
        guint8     *suffix;

        /* Check that there's enough data */
        if (tvb_length(tvb) < 3)
                return;

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

        is_request = (pinfo->match_port == pinfo->destport);
        elcom_len  = tvb_get_ntohs(tvb, 0);
        length_ok  = (tvb_reported_length(tvb) == (elcom_len+2));

        col_add_fstr(pinfo->cinfo, COL_INFO, "%s Len=%d%s",
                             is_request ? "Request" : "Response",
                             elcom_len,
                             length_ok ? "" : " (incorrect)");

        elcom_msg_type = tvb_get_guint8(tvb, 2);
        switch (elcom_msg_type) {
                case P_CONRQ:
                case P_CONRS:

                        /* starting after elcom_len and elcom_msg_type,
                           initiator + responder + userdata fields must be there */
                        if (tvb_length_remaining(tvb, 3+TOTAL_LEN+TOTAL_LEN+3) < 0) return;
                        /* check also that those field lengths are valid */
                        if (tvb_get_guint8(tvb, 3)  != LOWADR_LEN) return;
                        if (tvb_get_guint8(tvb, 3+1+LOWADR_LEN) != SUFFIX_LEN) return;
                        if (tvb_get_guint8(tvb, 3+TOTAL_LEN) != LOWADR_LEN) return;
                        if (tvb_get_guint8(tvb, 3+1+TOTAL_LEN+LOWADR_LEN) != SUFFIX_LEN) return;

                        /* finally believe that there is valid suffix */
                        suffix = tvb_get_string(wmem_packet_scope(), tvb, 3+2+LOWADR_LEN, 2);
                        col_append_fstr(pinfo->cinfo, COL_INFO, " %s Connect", suffix);
                        break;

                case P_RELRQ:
                case P_RELRS:
                        col_append_str(pinfo->cinfo, COL_INFO, " Release");
                        break;

                case P_DATRQ:
                        col_append_str(pinfo->cinfo, COL_INFO, " Data");
                        break;
                }

                switch (elcom_msg_type) {
                case P_CONRQ:
                case P_RELRQ:
                        col_append_str(pinfo->cinfo, COL_INFO, " Request");
                        break;

                case P_CONRS:
                case P_RELRS:
                        col_append_str(pinfo->cinfo, COL_INFO, " Response");
                        break;
        }

        if (!tree)
                return;

        ti = proto_tree_add_item(tree, proto_elcom, tvb, offset, -1, ENC_NA);
        elcom_tree = proto_item_add_subtree(ti, ett_elcom);

        hidden_item = proto_tree_add_boolean(elcom_tree,
                                             is_request ? hf_elcom_request : hf_elcom_response,
                                             tvb, 0, 0, TRUE);
        PROTO_ITEM_SET_HIDDEN(hidden_item);

        /* 2 first bytes are the frame length */
        offset = 0;
        ti = proto_tree_add_item(elcom_tree, hf_elcom_length, tvb, offset, 2, ENC_BIG_ENDIAN);
        offset = +2;
        if (! length_ok) {
                proto_item_append_text(ti, " (incorrect)");
        }

        elcom_msg_type = tvb_get_guint8(tvb, offset);
        ti = proto_tree_add_item(elcom_tree, hf_elcom_type, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_item_append_text(elcom_tree, " ( %s)", val_to_str(elcom_msg_type, type_vals, "Unknown %d"));

        offset++;
        if (tvb_length_remaining(tvb, offset) <= 0)
                return;

        switch (elcom_msg_type) {
        case P_CONRQ:
        case P_CONRS:
                /*
                 * Connection request/release assiciated PDU's,
                 * /ELCOM-90 P Protocol spec/ p. 85...
                 */

                /* We need the length here, hardcode the LOWADR_LEN = 21 */
                ti = proto_tree_add_item(elcom_tree, hf_elcom_initiator, tvb, offset, TOTAL_LEN, ENC_BIG_ENDIAN);
                offset = dissect_lower_address(ti, ett_elcom_initiator, tvb, offset,
                                               hf_elcom_initiator_endian,
                                               hf_elcom_initiator_ip,
                                               hf_elcom_initiator_port,
                                               hf_elcom_initiator_suff);
                if (tvb_length_remaining(tvb, offset) <= 0)
                        return;

                ti = proto_tree_add_item(elcom_tree, hf_elcom_responder, tvb, offset, TOTAL_LEN, ENC_BIG_ENDIAN);
                offset = dissect_lower_address(ti, ett_elcom_responder, tvb, offset,
                                               hf_elcom_responder_endian,
                                               hf_elcom_responder_ip,
                                               hf_elcom_responder_port,
                                               hf_elcom_responder_suff);
                if (tvb_length_remaining(tvb, offset) <= 0)
                        return;

                /* Rest of the payload is USER-DATA, 0..82 bytes */
                ti = proto_tree_add_item(elcom_tree, hf_elcom_userdata, tvb, offset, -1, ENC_NA);
                offset = dissect_userdata(ti, ett_elcom_userdata, tvb, offset);

                break;

        case P_RELRQ:

                proto_tree_add_item(elcom_tree, hf_elcom_release_reason, tvb, offset, 1, ENC_BIG_ENDIAN);
                offset += 1;

                break;
        case P_RELRS:

                proto_tree_add_item(elcom_tree, hf_elcom_release_result, tvb, offset, 1, ENC_BIG_ENDIAN);

                offset += 1;

                break;

        case P_DATRQ:
                ti = proto_tree_add_item(elcom_tree, hf_elcom_datarequest, tvb, offset, -1, ENC_NA);
                offset = dissect_datarequest(ti, ett_elcom_datarequest, tvb, offset);
                break;

        default:
                proto_item_append_text(ti, " <<--- meaning WHAT??");
                break;
        }


        if (tvb_length_remaining(tvb, offset) <= 0)
                return;

        /* We should not get here, but if we do, show what is left over: */
        ti = proto_tree_add_item(elcom_tree, hf_elcom_strangeleftover, tvb, offset, -1, ENC_NA);
        while (tvb_length_remaining(tvb, offset) > 0) {
                proto_item_append_text(ti, elcom_show_hex ? " %02x" : " %03o",
                                       tvb_get_guint8(tvb, offset));
                offset++;
        }
}
Esempio n. 14
0
static void
dissect_drda(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    gint offset = 0;

    guint16 iCommand;
    guint16 iLength;
    guint16 iCommandEnd = 0;

    guint8 iFormatFlags;
    guint8 iDSSType;
    guint8 iDSSFlags;

    guint16 iParameterCP;
    gint iLengthParam;

    col_set_str(pinfo->cinfo, COL_PROTOCOL, "DRDA");
    /* This is a trick to know whether this is the first PDU in this packet or not */
    if (iPreviousFrameNumber != pinfo->fd->num)
        col_clear(pinfo->cinfo, COL_INFO);
    else
        col_append_str(pinfo->cinfo, COL_INFO, " | ");

    iPreviousFrameNumber = pinfo->fd->num;
    /* There may be multiple DRDA commands in one frame */
    while ((guint) (offset + 10) <= tvb_length(tvb))
    {
        iCommand = tvb_get_ntohs(tvb, offset + 8);
        iLength = tvb_get_ntohs(tvb, offset + 0);
        if (iLength < 10) {
            expert_add_info_format_text(pinfo, NULL, &ei_drda_opcode_invalid_length, "Invalid length detected (%u): should be at least 10 bytes long", iLength);
            break;
        }
        /* iCommandEnd is the length of the packet up to the end of the current command */
        iCommandEnd += iLength;

        if (offset > 0)
            col_append_str(pinfo->cinfo, COL_INFO, " | ");
        col_append_str(pinfo->cinfo, COL_INFO, val_to_str_ext(iCommand, &drda_opcode_abbr_ext, "Unknown (0x%02x)"));

        if (tree)
        {
            proto_tree  *drda_tree;
            proto_tree  *drdaroot_tree;
            proto_tree  *drda_tree_sub;
            proto_item  *ti;

            ti = proto_tree_add_item(tree, proto_drda, tvb, offset, -1, ENC_NA);
            proto_item_append_text(ti, " (%s)", val_to_str_ext(iCommand, &drda_opcode_vals_ext, "Unknown (0x%02x)"));
            drdaroot_tree = proto_item_add_subtree(ti, ett_drda);

            ti = proto_tree_add_text(drdaroot_tree, tvb, offset, 10, DRDA_TEXT_DDM);
            proto_item_append_text(ti, " (%s)", val_to_str_ext(iCommand, &drda_opcode_abbr_ext, "Unknown (0x%02x)"));
            drda_tree = proto_item_add_subtree(ti, ett_drda_ddm);

            proto_tree_add_item(drda_tree, hf_drda_ddm_length, tvb, offset + 0, 2, ENC_BIG_ENDIAN);
            proto_tree_add_item(drda_tree, hf_drda_ddm_magic, tvb, offset + 2, 1, ENC_BIG_ENDIAN);

            iFormatFlags = tvb_get_guint8(tvb, offset + 3);
            iDSSType = iFormatFlags & 0x0F;
            iDSSFlags = iFormatFlags >> 4;

            ti = proto_tree_add_item(drda_tree, hf_drda_ddm_format, tvb, offset + 3, 1, ENC_BIG_ENDIAN);
            drda_tree_sub = proto_item_add_subtree(ti, ett_drda_ddm_format);

            proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_reserved, tvb, offset + 3, 1, iDSSFlags);
            proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_chained, tvb, offset + 3, 1, iDSSFlags);
            proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_errcont, tvb, offset + 3, 1, iDSSFlags);
            proto_tree_add_boolean(drda_tree_sub, hf_drda_ddm_fmt_samecorr, tvb, offset + 3, 1, iDSSFlags);
            proto_tree_add_uint(drda_tree_sub, hf_drda_ddm_fmt_dsstyp, tvb, offset + 3, 1, iDSSType);

            proto_tree_add_item(drda_tree, hf_drda_ddm_rc, tvb, offset + 4, 2, ENC_BIG_ENDIAN);
            proto_tree_add_item(drda_tree, hf_drda_ddm_length2, tvb, offset + 6, 2, ENC_BIG_ENDIAN);
            proto_tree_add_item(drda_tree, hf_drda_ddm_codepoint, tvb, offset + 8, 2, ENC_BIG_ENDIAN);

            /* The number of attributes is variable */
            for (offset += 10; offset < iCommandEnd; )
            {
                if (tvb_length_remaining(tvb, offset) >= 2)
                {
                    iLengthParam = tvb_get_ntohs(tvb, offset + 0);
                    if (iLengthParam == 0 || iLengthParam == 1) iLengthParam = iLength - 10;
                    if (tvb_length_remaining(tvb, offset) >= iLengthParam)
                    {
                        iParameterCP = tvb_get_ntohs(tvb, offset + 2);
                        ti = proto_tree_add_text(drdaroot_tree, tvb, offset, iLengthParam,
                                     DRDA_TEXT_PARAM);
                        proto_item_append_text(ti, " (%s)", val_to_str_ext(iParameterCP, &drda_opcode_vals_ext, "Unknown (0x%02x)"));
                        drda_tree_sub = proto_item_add_subtree(ti, ett_drda_param);
                        proto_tree_add_item(drda_tree_sub, hf_drda_param_length, tvb, offset, 2, ENC_BIG_ENDIAN);
                        proto_tree_add_item(drda_tree_sub, hf_drda_param_codepoint, tvb, offset + 2, 2, ENC_BIG_ENDIAN);
                        proto_tree_add_item(drda_tree_sub, hf_drda_param_data, tvb, offset + 4, iLengthParam - 4, ENC_UTF_8|ENC_NA);
                        proto_tree_add_item(drda_tree_sub, hf_drda_param_data_ebcdic, tvb, offset + 4, iLengthParam - 4, ENC_EBCDIC|ENC_NA);
                        if (iCommand == DRDA_CP_SQLSTT)
                        {
                            /* Extract SQL statement from packet */
                            tvbuff_t* next_tvb = NULL;
                            next_tvb = tvb_new_subset(tvb, offset + 4, iLengthParam - 4, iLengthParam - 4);
                            add_new_data_source(pinfo, next_tvb, "SQL statement");
                            proto_tree_add_item(drdaroot_tree, hf_drda_sqlstatement, next_tvb, 0, iLengthParam - 5, ENC_UTF_8|ENC_NA);
                            proto_tree_add_item(drdaroot_tree, hf_drda_sqlstatement_ebcdic, next_tvb, 0, iLengthParam - 4, ENC_EBCDIC|ENC_NA);
                        }
                    }
                    offset += iLengthParam;
                }
                else
                {
                    break;
                }
            }
        }
        else
        {
            /* No tree, advance directly to next command */
            offset += iLength;
        }
    }
Esempio n. 15
0
static void
dissect_exec(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	/* Set up structures needed to add the protocol subtree and manage it */
	proto_item *ti;
	proto_tree *exec_tree=NULL;

	/* Variables for extracting and displaying data from the packet */
	guchar *field_stringz; /* Temporary storage for each field we extract */

	gint length;
	guint offset = 0;
	conversation_t *conversation;
	exec_hash_entry_t *hash_info;

	conversation = find_or_create_conversation(pinfo);

	/* Retrieve information from conversation
	 * or add it if it isn't there yet
	 */
	hash_info = (exec_hash_entry_t *)conversation_get_proto_data(conversation, proto_exec);
	if(!hash_info){
		hash_info = wmem_new(wmem_file_scope(), exec_hash_entry_t);

		hash_info->first_packet_number = pinfo->fd->num;
		hash_info->second_packet_number = 0;
		hash_info->third_packet_number  = 0;
		hash_info->fourth_packet_number  = 0;

		hash_info->state = WAIT_FOR_STDERR_PORT; /* The first field we'll see */

		/* Start with empty username and command strings */
		hash_info->username=NULL;
		hash_info->command=NULL;

		/* These will be set on the first pass by the first
		 * four packets of the conversation
		 */
		hash_info->first_packet_state  = NONE;
		hash_info->second_packet_state = NONE;
		hash_info->third_packet_state  = NONE;
		hash_info->fourth_packet_state  = NONE;

		conversation_add_proto_data(conversation, proto_exec, hash_info);
	}

	/* Store the number of the first three packets of this conversation
	 * as we reach them the first time */

	if(!hash_info->second_packet_number
	&& pinfo->fd->num > hash_info->first_packet_number){
		/* We're on the second packet of the conversation */
		hash_info->second_packet_number = pinfo->fd->num;
	} else if(hash_info->second_packet_number
	 && !hash_info->third_packet_number
	 && pinfo->fd->num > hash_info->second_packet_number) {
		/* We're on the third packet of the conversation */
		hash_info->third_packet_number = pinfo->fd->num;
	} else if(hash_info->third_packet_number
	 && !hash_info->fourth_packet_number
	 && pinfo->fd->num > hash_info->third_packet_number) {
		/* We're on the fourth packet of the conversation */
		hash_info->fourth_packet_number = pinfo->fd->num;
	}

	/* Save this packet's state so we can retrieve it if this packet
	 * is selected again later.  If the packet's state was already stored,
	 * then retrieve it */
	if(pinfo->fd->num == hash_info->first_packet_number){
		if(hash_info->first_packet_state == NONE){
			hash_info->first_packet_state = hash_info->state;
		} else {
			hash_info->state = hash_info->first_packet_state;
		}
	}

	if(pinfo->fd->num == hash_info->second_packet_number){
		if(hash_info->second_packet_state == NONE){
			hash_info->second_packet_state = hash_info->state;
		} else {
			hash_info->state = hash_info->second_packet_state;
		}
	}

	if(pinfo->fd->num == hash_info->third_packet_number){
		if(hash_info->third_packet_state == NONE){
			hash_info->third_packet_state = hash_info->state;
		} else {
			hash_info->state = hash_info->third_packet_state;
		}
	}

	if(pinfo->fd->num == hash_info->fourth_packet_number){
		if(hash_info->fourth_packet_state == NONE){
			hash_info->fourth_packet_state = hash_info->state;
		} else {
			hash_info->state = hash_info->fourth_packet_state;
		}
	}

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

	/* First, clear the info column */
	col_clear(pinfo->cinfo, COL_INFO);

	/*username */
	if(hash_info->username && preference_info_show_username == TRUE){
		col_append_fstr(pinfo->cinfo, COL_INFO, "Username:%s ", hash_info->username);
	}

	/* Command */
	if(hash_info->command && preference_info_show_command == TRUE){
		col_append_fstr(pinfo->cinfo, COL_INFO, "Command:%s ", hash_info->command);
	}

	/* create display subtree for the protocol */
	ti = proto_tree_add_item(tree, proto_exec, tvb, 0, -1, ENC_NA);
	exec_tree = proto_item_add_subtree(ti, ett_exec);

	/* If this packet doesn't end with a null terminated string,
	 * then it must be session data only and we can skip looking
	 * for the other fields.
	 */
	if(tvb_find_guint8(tvb, tvb_length(tvb)-1, 1, '\0') == -1){
		hash_info->state = WAIT_FOR_DATA;
	}

	if(hash_info->state == WAIT_FOR_STDERR_PORT
	&& tvb_length_remaining(tvb, offset)){
		field_stringz = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &length, ENC_ASCII);

		/* Check if this looks like the stderr_port field.
		 * It is optional, so it may only be 1 character long
		 * (the NULL)
		 */
		if(length == 1 || (isdigit_string(field_stringz)
		&& length <= EXEC_STDERR_PORT_LEN)){
			proto_tree_add_string(exec_tree, hf_exec_stderr_port, tvb, offset, length, (gchar*)field_stringz);
			 /* Next field we need */
			hash_info->state = WAIT_FOR_USERNAME;
		} else {
			/* Since the data doesn't match this field, it must be data only */
			hash_info->state = WAIT_FOR_DATA;
		}

		/* Used if the next field is in the same packet */
		offset += length;
	}


	if(hash_info->state == WAIT_FOR_USERNAME
	&& tvb_length_remaining(tvb, offset)){
		field_stringz = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &length, ENC_ASCII);

		/* Check if this looks like the username field */
		if(length != 1 && length <= EXEC_USERNAME_LEN
		&& isprint_string(field_stringz)){
			proto_tree_add_string(exec_tree, hf_exec_username, tvb, offset, length, (gchar*)field_stringz);

			/* Store the username so we can display it in the
			 * info column of the entire conversation
			 */
			if(!hash_info->username){
				hash_info->username=wmem_strdup(wmem_file_scope(), (gchar*)field_stringz);
			}

			 /* Next field we need */
			hash_info->state = WAIT_FOR_PASSWORD;
		} else {
			/* Since the data doesn't match this field, it must be data only */
			hash_info->state = WAIT_FOR_DATA;
		}

		/* Used if the next field is in the same packet */
		offset += length;
	}


	if(hash_info->state == WAIT_FOR_PASSWORD
	&& tvb_length_remaining(tvb, offset)){
		field_stringz = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &length, ENC_ASCII);

		/* Check if this looks like the password field */
		if(length != 1 && length <= EXEC_PASSWORD_LEN
		&& isprint_string(field_stringz)){
			proto_tree_add_string(exec_tree, hf_exec_password, tvb, offset, length, (gchar*)field_stringz);

			/* Next field we need */
			hash_info->state = WAIT_FOR_COMMAND;
		} else {
			/* Since the data doesn't match this field, it must be data only */
			hash_info->state = WAIT_FOR_DATA;
		}

		/* Used if the next field is in the same packet */
		offset += length;
		 /* Next field we are looking for */
		hash_info->state = WAIT_FOR_COMMAND;
	}


	if(hash_info->state == WAIT_FOR_COMMAND
	&& tvb_length_remaining(tvb, offset)){
		field_stringz = tvb_get_stringz_enc(wmem_packet_scope(), tvb, offset, &length, ENC_ASCII);

		/* Check if this looks like the command field */
		if(length != 1 && length <= EXEC_COMMAND_LEN
		&& isprint_string(field_stringz)){
			proto_tree_add_string(exec_tree, hf_exec_command, tvb, offset, length, (gchar*)field_stringz);

			/* Store the command so we can display it in the
			 * info column of the entire conversation
			 */
			if(!hash_info->command){
				hash_info->command=wmem_strdup(wmem_file_scope(), (gchar*)field_stringz);
			}

		} else {
			/* Since the data doesn't match this field, it must be data only */
			hash_info->state = WAIT_FOR_DATA;
		}
	}


	if(hash_info->state == WAIT_FOR_DATA
	&& tvb_length_remaining(tvb, offset)){
		if(pinfo->destport == EXEC_PORT){
			/* Packet going to the server */
			/* offset = 0 since the whole packet is data */
			proto_tree_add_item(exec_tree, hf_exec_client_server_data, tvb, 0, -1, ENC_NA);

			col_append_str(pinfo->cinfo, COL_INFO, "Client -> Server data");
		} else {
			/* This packet must be going back to the client */
			/* offset = 0 since the whole packet is data */
			proto_tree_add_item(exec_tree, hf_exec_server_client_data, tvb, 0, -1, ENC_NA);

			col_append_str(pinfo->cinfo, COL_INFO, "Server -> Client Data");
		}
	}

	/* We haven't seen all of the fields yet */
	if(hash_info->state < WAIT_FOR_DATA){
		col_set_str(pinfo->cinfo, COL_INFO, "Session Establishment");
	}
}
static void
rs11(tvbuff_t *tvb, proto_tree *tree)
{
	proto_tree_add_item(tree, hf_ipmi_stor_11_ret_count, tvb, 0, 1, ENC_LITTLE_ENDIAN);
	proto_tree_add_item(tree, hf_ipmi_stor_11_data, tvb, 1, tvb_length(tvb) - 1, ENC_NA);
}
Esempio n. 17
0
static int
dissect_gopher(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree) {
    proto_item *ti;
    proto_tree *gopher_tree, *dir_tree = NULL;
    gboolean client = is_client(pinfo);
    gint line_len;
    const gchar *request = "[Invalid request]";
    gboolean is_dir = FALSE;
    gint offset = 0, next_offset;
    gint sel_start, host_start, port_start;
    gchar *name;

    /* Fill in our protocol and info columns */
    col_set_str(pinfo->cinfo, COL_PROTOCOL, "Gopher");

    if (client) {
        line_len = tvb_find_line_end(tvb, 0, -1, NULL, FALSE);
        if (line_len == 0) {
            request = "[Directory list]";
        } else if (line_len > 0) {
            request = tvb_get_ephemeral_string(tvb, 0, line_len);
        }
        col_add_fstr(pinfo->cinfo, COL_INFO, "Request: %s", request);
    } else {
        col_add_fstr(pinfo->cinfo, COL_INFO, "Response");
    }

    if (tree) {
        /* Create display subtree for the protocol */
        ti = proto_tree_add_item(tree, proto_gopher, tvb, 0, -1, ENC_NA);
        gopher_tree = proto_item_add_subtree(ti, ett_gopher);

        if (client) {
            proto_item_append_text(ti, " request: %s", request);
            proto_tree_add_string(gopher_tree, hf_gopher_request, tvb,
                                  0, -1, request);
        } else {
            proto_item_append_text(ti, " response: ");

            while (find_dir_tokens(tvb, offset + 1, &sel_start, &host_start, &port_start, &line_len, &next_offset)) {
                if (!is_dir) { /* First time */
                    proto_item_append_text(ti, "[Directory list]");
                    col_append_fstr(pinfo->cinfo, COL_INFO, ": [Directory list]");
                }

                name = tvb_get_string(tvb, offset + 1, sel_start - offset - 2);
                ti = proto_tree_add_string(gopher_tree, hf_gopher_dir_item, tvb,
                                offset, line_len + 1, name);
                g_free(name);
                dir_tree = proto_item_add_subtree(ti, ett_dir_item);
                proto_tree_add_item(dir_tree, hf_gopher_di_type, tvb, offset, 1, ENC_BIG_ENDIAN);
                proto_tree_add_item(dir_tree, hf_gopher_di_name, tvb, offset + 1,
                                    sel_start - offset - 2, ENC_ASCII|ENC_NA);
                proto_tree_add_item(dir_tree, hf_gopher_di_selector, tvb, sel_start,
                                    host_start - sel_start - 1, ENC_ASCII|ENC_NA);
                proto_tree_add_item(dir_tree, hf_gopher_di_host, tvb, host_start,
                                    port_start - host_start - 1, ENC_ASCII|ENC_NA);
                proto_tree_add_item(dir_tree, hf_gopher_di_port, tvb, port_start,
                                    line_len - (port_start - offset - 1), ENC_ASCII|ENC_NA);
                is_dir = TRUE;
                offset = next_offset;
            }

            if (!is_dir) {
                proto_item_append_text(ti, "[Unknown]");
                proto_tree_add_item(gopher_tree, hf_gopher_unknown, tvb, 0, -1, ENC_ASCII|ENC_NA);
            }
        }

    }

    /* Return the amount of data this dissector was able to dissect */
    return tvb_length(tvb);
}
static void
rs43(tvbuff_t *tvb, proto_tree *tree)
{
	proto_tree_add_item(tree, hf_ipmi_stor_43_next, tvb, 0, 2, ENC_LITTLE_ENDIAN);
	proto_tree_add_item(tree, hf_ipmi_stor_43_data, tvb, 2, tvb_length(tvb) - 2, ENC_NA);
}
Esempio n. 19
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 */
static void
rq44(tvbuff_t *tvb, proto_tree *tree)
{
	proto_tree_add_item(tree, hf_ipmi_stor_44_data, tvb, 0, tvb_length(tvb), ENC_NA);
}
Esempio n. 21
0
/*FUNCTION:------------------------------------------------------
 *  NAME
 *      dissect_zbee_secure
 *  DESCRIPTION
 *      Dissects and decrypts secured ZigBee frames.
 *
 *      Will return a valid tvbuff only if security processing was
 *      successful. If processing fails, then this function will
 *      handle internally and return NULL.
 *  PARAMETERS
 *      tvbuff_t    *tvb    - pointer to buffer containing raw packet.
 *      packet_info *pinfo  - pointer to packet information fields
 *      proto_tree  *tree   - pointer to data tree Wireshark uses to display packet.
 *      guint       offset  - pointer to the start of the auxilliary security header.
 *      guint64     src64   - extended source address, or 0 if unknown.
 *  RETURNS
 *      tvbuff_t *
 *---------------------------------------------------------------
 */
tvbuff_t *
dissect_zbee_secure(tvbuff_t *tvb, packet_info *pinfo, proto_tree* tree, guint offset)
{
    proto_tree     *sec_tree = NULL;
    proto_item     *sec_root;
    proto_tree     *field_tree;
    proto_item     *ti;

    zbee_security_packet    packet;
    guint           mic_len;
    gint            payload_len;
    tvbuff_t       *payload_tvb;

#ifdef HAVE_LIBGCRYPT
    guint8             *enc_buffer;
    guint8             *dec_buffer;
    gboolean            decrypted;
    GSList            **nwk_keyring;
    GSList             *GSList_i;
    key_record_t       *key_rec = NULL;
#endif
    zbee_nwk_hints_t   *nwk_hints;
    ieee802154_hints_t *ieee_hints;
    ieee802154_map_rec *map_rec = NULL;

    /* Init */
    memset(&packet, 0, sizeof(zbee_security_packet));

    /* Get pointers to any useful frame data from lower layers */
    nwk_hints = (zbee_nwk_hints_t *)p_get_proto_data(pinfo->fd, proto_get_id_by_filter_name(ZBEE_PROTOABBREV_NWK));
    ieee_hints = (ieee802154_hints_t *)p_get_proto_data(pinfo->fd,
    proto_get_id_by_filter_name(IEEE802154_PROTOABBREV_WPAN));

    /* Create a subtree for the security information. */
    if (tree) {
        sec_root = proto_tree_add_text(tree, tvb, offset, tvb_length_remaining(tvb, offset), "ZigBee Security Header");
        sec_tree = proto_item_add_subtree(sec_root, ett_zbee_sec);
    }

    /*  Get and display the Security control field */
    packet.control  = tvb_get_guint8(tvb, offset);

    /* Patch the security level. */
    packet.control &= ~ZBEE_SEC_CONTROL_LEVEL;
    packet.control |= (ZBEE_SEC_CONTROL_LEVEL & gPREF_zbee_sec_level);

    /*
     * Eww, I think I just threw up a little...  ZigBee requires this field
     * to be patched before computing the MIC, but we don't have write-access
     * to the tvbuff. So we need to allocate a copy of the whole thing just
     * so we can fix these 3 bits. Memory allocated by ep_tvb_memdup() is
     * automatically freed before the next packet is processed.
     */
#ifdef HAVE_LIBGCRYPT
    enc_buffer = (guint8 *)ep_tvb_memdup(tvb, 0, tvb_length(tvb));
    /*
     * Override the const qualifiers and patch the security level field, we
     * know it is safe to overide the const qualifiers because we just
     * allocated this memory via ep_tvb_memdup().
     */
    enc_buffer[offset] = packet.control;
#endif /* HAVE_LIBGCRYPT */
    packet.level    = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_LEVEL);
    packet.key_id   = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_KEY);
    packet.nonce    = zbee_get_bit_field(packet.control, ZBEE_SEC_CONTROL_NONCE);
    if (tree) {
        ti = proto_tree_add_text(sec_tree, tvb, offset, 1, "Security Control Field");
        field_tree = proto_item_add_subtree(ti, ett_zbee_sec_control);

        proto_tree_add_uint(field_tree, hf_zbee_sec_key_id, tvb, offset, 1,
                                packet.control & ZBEE_SEC_CONTROL_KEY);
        proto_tree_add_boolean(field_tree, hf_zbee_sec_nonce, tvb, offset, 1,
                                packet.control & ZBEE_SEC_CONTROL_NONCE);
    }
    offset += 1;

    /* Get and display the frame counter field. */
    packet.counter = tvb_get_letohl(tvb, offset);
    if (tree) {
        proto_tree_add_uint(sec_tree, hf_zbee_sec_counter, tvb, offset, 4, packet.counter);
    }
    offset += 4;

    if (packet.nonce) {
        /* Get and display the source address of the device that secured this payload. */
        packet.src64 = tvb_get_letoh64(tvb, offset);
        if (tree) {
            proto_tree_add_item(sec_tree, hf_zbee_sec_src64, tvb, offset, 8, ENC_LITTLE_ENDIAN);
        }
#if 1
        if (!pinfo->fd->flags.visited) {
            switch ( packet.key_id ) {
                case ZBEE_SEC_KEY_LINK:
                if (nwk_hints) {
                    /* Map this long address with the nwk layer short address. */
                    nwk_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, nwk_hints->src,
                            ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->fd->num);
                }
                break;

                case ZBEE_SEC_KEY_NWK:
                if (ieee_hints) {
                    /* Map this long address with the ieee short address. */
                    ieee_hints->map_rec = ieee802154_addr_update(&zbee_nwk_map, ieee_hints->src16,
                        ieee_hints->src_pan, packet.src64, pinfo->current_proto, pinfo->fd->num);
                }
                break;

                /* We ignore the extended source addresses used to encrypt payloads with these
                 * types of keys, because they can emerge from APS tunnels created by nodes whose
                 * short address is not recorded in the packet. */
                case ZBEE_SEC_KEY_TRANSPORT:
                case ZBEE_SEC_KEY_LOAD:
                break;
            }
        }
#endif
        offset += 8;
    }
    else {
        /* Look for a source address in hints */
        switch ( packet.key_id ) {
            case ZBEE_SEC_KEY_NWK:
                /* use the ieee extended source address for NWK decryption */
                if ( ieee_hints && (map_rec = ieee_hints->map_rec) ) packet.src64 = map_rec->addr64;
                else if (tree) proto_tree_add_text(sec_tree, tvb, 0, 0, "[Extended Source: Unknown]");
                break;

            default:
                /* use the nwk extended source address for APS decryption */
                if ( nwk_hints && (map_rec = nwk_hints->map_rec) ) packet.src64 = map_rec->addr64;
                else if (tree) proto_tree_add_text(sec_tree, tvb, 0, 0, "[Extended Source: Unknown]");
                break;
        }
    }

    if (packet.key_id == ZBEE_SEC_KEY_NWK) {
        /* Get and display the key sequence number. */
        packet.key_seqno = tvb_get_guint8(tvb, offset);
        if (tree) {
            proto_tree_add_uint(sec_tree, hf_zbee_sec_key_seqno, tvb, offset, 1, packet.key_seqno);
        }
        offset += 1;
    }

    /* Determine the length of the MIC. */
    switch (packet.level) {
        case ZBEE_SEC_ENC:
        case ZBEE_SEC_NONE:
        default:
            mic_len=0;
            break;

        case ZBEE_SEC_ENC_MIC32:
        case ZBEE_SEC_MIC32:
            mic_len=4;
            break;

        case ZBEE_SEC_ENC_MIC64:
        case ZBEE_SEC_MIC64:
            mic_len=8;
            break;

        case ZBEE_SEC_ENC_MIC128:
        case ZBEE_SEC_MIC128:
            mic_len=16;
            break;
    } /* switch */

    /* Get and display the MIC. */
    if (mic_len) {
        /* Display the MIC. */
        if (tree) {
            proto_tree_add_item(sec_tree, hf_zbee_sec_mic, tvb, (gint)(tvb_length(tvb)-mic_len),
                   mic_len, ENC_NA);
        }
    }

    /* Check for null payload. */
    if ( !(payload_len = tvb_reported_length_remaining(tvb, offset+mic_len)) ) {
        return NULL;
    } else if ( payload_len < 0 ) {
        THROW(ReportedBoundsError);
    }

    /**********************************************
     *  Perform Security Operations on the Frame  *
     **********************************************
     */
    if ((packet.level == ZBEE_SEC_NONE) ||
        (packet.level == ZBEE_SEC_MIC32) ||
        (packet.level == ZBEE_SEC_MIC64) ||
        (packet.level == ZBEE_SEC_MIC128)) {

        /* Payload is only integrity protected. Just return the sub-tvbuff. */
        return tvb_new_subset(tvb, offset, payload_len, payload_len);
    }

#ifdef HAVE_LIBGCRYPT
    /* Allocate memory to decrypt the payload into. */
    dec_buffer = (guint8 *)g_malloc(payload_len);

    decrypted = FALSE;
    if ( packet.src64 ) {
        if (pinfo->fd->flags.visited) {
            if ( nwk_hints ) {
                /* Use previously found key */
                switch ( packet.key_id ) {
                    case ZBEE_SEC_KEY_NWK:
                        if ( (key_rec = nwk_hints->nwk) ) {
                            decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                payload_len, mic_len, nwk_hints->nwk->key);
                        }
                        break;

                    default:
                        if ( (key_rec = nwk_hints->link) ) {
                            decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                payload_len, mic_len, nwk_hints->link->key);
                        }
                        break;
                }
            }
        } /* ( !pinfo->fd->flags.visited ) */
        else {
            /* We only search for sniffed keys in the first pass,
             * to save time, and because decrypting with keys
             * transported in future packets is cheating */

            /* Lookup NWK and link key in hash for this pan. */
            /* This overkill approach is a placeholder for a hash that looks up
             * a key ring for a link key associated with a pair of devices.
             */
            if ( nwk_hints ) {
                nwk_keyring = (GSList **)g_hash_table_lookup(zbee_table_nwk_keyring, &nwk_hints->src_pan);

                if ( nwk_keyring ) {
                    GSList_i = *nwk_keyring;
                    while ( GSList_i && !decrypted ) {
                        decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                                payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key);

                        if (decrypted) {
                            /* save pointer to the successful key record */
                            switch (packet.key_id) {
                                case ZBEE_SEC_KEY_NWK:
                                    key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data);
                                    break;

                                default:
                                    key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data);
                                    break;
                            }
                        } else {
                            GSList_i = g_slist_next(GSList_i);
                        }
                    }
                }

                /* Loop through user's password table for preconfigured keys, our last resort */
                GSList_i = zbee_pc_keyring;
                while ( GSList_i && !decrypted ) {
                    decrypted = zbee_sec_decrypt_payload( &packet, enc_buffer, offset, dec_buffer,
                            payload_len, mic_len, ((key_record_t *)(GSList_i->data))->key);

                    if (decrypted) {
                        /* save pointer to the successful key record */
                        switch (packet.key_id) {
                            case ZBEE_SEC_KEY_NWK:
                                key_rec = nwk_hints->nwk = (key_record_t *)(GSList_i->data);
                                break;

                            default:
                                key_rec = nwk_hints->link = (key_record_t *)(GSList_i->data);
                                break;
                        }
                    } else {
                        GSList_i = g_slist_next(GSList_i);
                    }
                }
            }
        } /* ( ! pinfo->fd->flags.visited ) */
    } /* ( packet.src64 ) */

    if ( decrypted ) {
        if ( tree && key_rec ) {
            if ( key_rec->frame_num == ZBEE_SEC_PC_KEY ) {
                ti = proto_tree_add_text(sec_tree, tvb, 0, 0, "Decryption Key: %s", key_rec->label);
            } else {
                ti = proto_tree_add_uint(sec_tree, hf_zbee_sec_key_origin, tvb, 0, 0,
                        key_rec->frame_num);
            }
            PROTO_ITEM_SET_GENERATED(ti);
        }

        /* Found a key that worked, setup the new tvbuff_t and return */
        payload_tvb = tvb_new_child_real_data(tvb, dec_buffer, payload_len, payload_len);
        tvb_set_free_cb(payload_tvb, g_free); /* set up callback to free dec_buffer */
        add_new_data_source(pinfo, payload_tvb, "Decrypted ZigBee Payload");

        /* Done! */
        return payload_tvb;
    }

    g_free(dec_buffer);
#endif /* HAVE_LIBGCRYPT */

    /* Add expert info. */
    expert_add_info_format(pinfo, sec_tree, PI_UNDECODED, PI_WARN, "Encrypted Payload");
    /* Create a buffer for the undecrypted payload. */
    payload_tvb = tvb_new_subset(tvb, offset, payload_len, -1);
    /* Dump the payload to the data dissector. */
    call_dissector(data_handle, payload_tvb, pinfo, tree);
    /* Couldn't decrypt, so return NULL. */
    return NULL;
} /* dissect_zbee_secure */
Esempio n. 22
0
static void
dissect_lapdm(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    proto_tree *lapdm_tree, *addr_tree, *length_tree;
    proto_item *lapdm_ti, *addr_ti, *length_ti;
    guint8 addr, length, cr, sapi, len/*, n_s*/;
    int control;
    gboolean m;
    tvbuff_t *payload;
    int available_length;
    gboolean is_response = FALSE;

    /* Check that there's enough data */
    if (tvb_length(tvb) < LAPDM_HEADER_LEN)
        return;

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

    addr = tvb_get_guint8(tvb, 0);
    length = tvb_get_guint8(tvb, 2);

    cr = addr & LAPDM_CR;
    if (pinfo->p2p_dir == P2P_DIR_RECV) {
        is_response = cr ? FALSE : TRUE;
    }
    else if (pinfo->p2p_dir == P2P_DIR_SENT) {
        is_response = cr ? TRUE : FALSE;
    }

    if (tree) {
        lapdm_ti = proto_tree_add_item(tree, proto_lapdm, tvb, 0, LAPDM_HEADER_LEN, ENC_NA);
        lapdm_tree = proto_item_add_subtree(lapdm_ti, ett_lapdm);

        addr_ti = proto_tree_add_uint(lapdm_tree, hf_lapdm_address, tvb, 0, 1, addr);
        addr_tree = proto_item_add_subtree(addr_ti, ett_lapdm_address);

        proto_tree_add_uint(addr_tree, hf_lapdm_lpd, tvb, 0, 1, addr);
        proto_tree_add_uint(addr_tree, hf_lapdm_sapi, tvb, 0, 1, addr);
        proto_tree_add_uint(addr_tree, hf_lapdm_cr, tvb, 0, 1, addr);
        proto_tree_add_uint(addr_tree, hf_lapdm_ea, tvb, 0, 1, addr);
    }
    else {
        lapdm_ti = NULL;
        lapdm_tree = NULL;
    }

    control = dissect_xdlc_control(tvb, 1, pinfo, lapdm_tree, hf_lapdm_control,
              ett_lapdm_control, &lapdm_cf_items, NULL /* LAPDm doesnt support extended */, NULL, NULL,
              is_response, FALSE, FALSE);

    if (tree) {
        length_ti = proto_tree_add_uint(lapdm_tree, hf_lapdm_length, tvb,
                    2, 1, length);
        length_tree = proto_item_add_subtree(length_ti, ett_lapdm_length);

        proto_tree_add_uint(length_tree, hf_lapdm_len, tvb, 2, 1, length);
        proto_tree_add_uint(length_tree, hf_lapdm_m, tvb, 2, 1, length);
        proto_tree_add_uint(length_tree, hf_lapdm_el, tvb, 2, 1, length);
    }

    sapi = (addr & LAPDM_SAPI) >> LAPDM_SAPI_SHIFT;
    len = (length & LAPDM_LEN) >> LAPDM_LEN_SHIFT;
    /*n_s = (control & XDLC_N_S_MASK) >> XDLC_N_S_SHIFT;*/
    m = (length & LAPDM_M) >> LAPDM_M_SHIFT;
    available_length = tvb_length(tvb) - LAPDM_HEADER_LEN;

    /* No point in doing anything if no payload
     */
    if( !MIN(len, available_length) )
        return;

    payload = tvb_new_subset(tvb, LAPDM_HEADER_LEN, MIN(len,available_length), -1);

    /* Potentially segmented I frame
     */
    if( (control & XDLC_I_MASK) == XDLC_I && reassemble_lapdm )
    {
            fragment_head *fd_m = NULL;
            tvbuff_t *reassembled = NULL;
            guint32 fragment_id;
            gboolean save_fragmented = pinfo->fragmented;

            pinfo->fragmented = m;

            /* Rely on caller to provide a way to group fragments */
            fragment_id = (pinfo->circuit_id << 4) | (sapi << 1) | pinfo->p2p_dir;

            /* This doesn't seem the best way of doing it as doesn't
               take N(S) into account, but N(S) isn't always 0 for
               the first fragment!
             */
            fd_m = fragment_add_seq_next (&lapdm_reassembly_table, payload, 0,
                                pinfo,
                                fragment_id, /* guint32 ID for fragments belonging together */
                                NULL,
                                /*n_s guint32 fragment sequence number */
                                len, /* guint32 fragment length */
                                m); /* More fragments? */

            reassembled = process_reassembled_data(payload, 0, pinfo,
                    "Reassembled LAPDm", fd_m, &lapdm_frag_items,
                    NULL, lapdm_tree);

            /* Reassembled into this packet
             */
            if (fd_m && pinfo->fd->num == fd_m->reassembled_in) {
                    if (!dissector_try_uint(lapdm_sapi_dissector_table, sapi,
                                reassembled, pinfo, tree))
                        call_dissector(data_handle, reassembled, pinfo, tree);
            }
            else {
                col_append_str(pinfo->cinfo, COL_INFO, " (Fragment)");
                if (tree) {
                    proto_tree_add_text(lapdm_tree, payload, 0, -1, "Fragment Data");
                }
            }

            /* Now reset fragmentation information in pinfo
             */
            pinfo->fragmented = save_fragmented;
    }
    else
    {
        /* Whole packet
           If we have some data, try and dissect it (only happens for UI, SABM, UA or I frames)
         */
        if (!dissector_try_uint(lapdm_sapi_dissector_table, sapi,
                payload, pinfo, tree))
            call_dissector(data_handle,payload, pinfo, tree);
    }
}
Esempio n. 23
0
static gint ett_miop = -1;

#define MIOP_MAGIC   "MIOP"

static void dissect_miop (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree);

static gboolean
dissect_miop_heur (tvbuff_t * tvb, packet_info * pinfo, proto_tree * tree, void * data _U_) {

  guint tot_len;

  /* check magic number and version */


  tot_len = tvb_length(tvb);

  if (tot_len < MIOP_HEADER_SIZE) /* tot_len < 16 */
    {
      /* Not enough data captured to hold the GIOP header; don't try
         to interpret it as GIOP. */
      return FALSE;
    }

  if ( tvb_memeql(tvb, 0, MIOP_MAGIC ,4) != 0)
    return FALSE;

  if (pinfo->ptype != PT_UDP)
    return FALSE;

  dissect_miop (tvb, pinfo, tree);
Esempio n. 24
0
                             guint32 start_off)
{
  guint32 offset;

  offset = start_off;

  /* AuthScheme */
  proto_tree_add_item(tree, hf_negoex_authscheme, tvb, offset, 16, ENC_LITTLE_ENDIAN);
  offset += 16;

  /* ErrorCode, an NTSTATUS :-) */
  proto_tree_add_item(tree, hf_negoex_errorcode, tvb, offset, 4, ENC_LITTLE_ENDIAN);
  offset += 4;

  /* The rest */
  proto_tree_add_text(tree, tvb, offset, tvb_length(tvb) - offset,
                      "The rest of the alert message");

}

static void
dissect_negoex_verify_message(tvbuff_t *tvb,
                              packet_info *pinfo _U_,
                              proto_tree *tree,
                              guint32 start_off)
{
  guint32 offset;
  guint32 checksum_vector_offset;
  guint32 checksum_vector_count;
  proto_item *pi;
  proto_tree *checksum;
Esempio n. 25
0
/* This function will try to determine the complete size of a PDU
 * based on the information in the header.
 */
static guint
get_nbd_tcp_pdu_len(packet_info *pinfo, tvbuff_t *tvb, int offset)
{
	guint32 magic, type, packet;
	conversation_t *conversation;
	nbd_conv_info_t *nbd_info;
	nbd_transaction_t *nbd_trans=NULL;
	wmem_tree_key_t hkey[3];
	guint32 handle[2];

	magic=tvb_get_ntohl(tvb, offset);

	switch(magic){
	case NBD_REQUEST_MAGIC:
		type=tvb_get_ntohl(tvb, offset+4);
		switch(type){
		case NBD_CMD_WRITE:
			return tvb_get_ntohl(tvb, offset+24)+28;
		default:
			return 28;
		}
	case NBD_RESPONSE_MAGIC:
		/*
		 * Do we have a conversation for this connection?
		 */
		conversation = find_conversation(pinfo->fd->num,
				&pinfo->src, &pinfo->dst,
				pinfo->ptype,
				pinfo->srcport, pinfo->destport, 0);
		if (conversation == NULL) {
			/* No, so just return the rest of the current packet */
			return tvb_length(tvb);
		}
		/*
		 * Do we have a state structure for this conv
		 */
		nbd_info = (nbd_conv_info_t *)conversation_get_proto_data(conversation, proto_nbd);
		if (!nbd_info) {
			/* No, so just return the rest of the current packet */
			return tvb_length(tvb);
		}
		if(!pinfo->fd->flags.visited){
			/*
			 * Do we have a state structure for this transaction
			 */
			handle[0]=tvb_get_ntohl(tvb, offset+8);
			handle[1]=tvb_get_ntohl(tvb, offset+12);
			hkey[0].length=2;
			hkey[0].key=handle;
			hkey[1].length=0;
			nbd_trans=(nbd_transaction_t *)wmem_tree_lookup32_array(nbd_info->unacked_pdus, hkey);
			if(!nbd_trans){
				/* No, so just return the rest of the current packet */
				return tvb_length(tvb);
			}
		} else {
			/*
			 * Do we have a state structure for this transaction
			 */
			handle[0]=tvb_get_ntohl(tvb, offset+8);
			handle[1]=tvb_get_ntohl(tvb, offset+12);
			packet=pinfo->fd->num;
			hkey[0].length=1;
			hkey[0].key=&packet;
			hkey[1].length=2;
			hkey[1].key=handle;
			hkey[2].length=0;
			nbd_trans=(nbd_transaction_t *)wmem_tree_lookup32_array(nbd_info->acked_pdus, hkey);
			if(!nbd_trans){
				/* No, so just return the rest of the current packet */
				return tvb_length(tvb);
			}
		}
		/* If this is a read response we must add the datalen to
		 * the pdu size
		 */
		if(nbd_trans->type==NBD_CMD_READ){
			return 16+nbd_trans->datalen;
		} else {
			return 16;
		}
	default:
		break;
	}

	/* Did not really look like a NBD packet after all */
	return 0;
}
Esempio n. 26
0
}

static int
dissect_dlm3(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void *data _U_)
{
  proto_item *item, *sub_item;
  proto_tree *tree, *sub_tree;

  int        offset;
  guint      length;
  guint32    h_version;
  guint8     h_cmd;


  /* Check that there's enough data */
  length = tvb_length(tvb);
  if (length < 4 + 4 + 4 + 2 + 1 + 1)
    return 0;

  /* Check the protocol version  */
  h_version = tvb_get_letohl(tvb, 0);
  if (h_version != (DLM3_MAJOR_VERSION|DLM3_MINOR_VERSION))
    return 0;

  /* Check the command */
  h_cmd = tvb_get_guint8(tvb, 4 + 4 + 4 + 2) ;
  if ((h_cmd != DLM3_MSG) && (h_cmd != DLM3_RCOM))
    return 0;

  if ((h_cmd == DLM3_MSG) && (length < ((4 + 4 + 4 + 2 + 1 + 1)
                                        + (4 * 12 + 4 * 6))))
Esempio n. 27
0
static int dissect_ProtocolExtensionFieldExtensionValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  return (dissector_try_uint(sbc_ap_extension_dissector_table, ProtocolExtensionID, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
}
Esempio n. 28
0
#include "ui/gtk/follow_stream.h"
#include "ui/gtk/keys.h"
#include "ui/gtk/main.h"
#include "ui/gtk/follow_udp.h"

static int
udp_queue_packet_data(void *tapdata, packet_info *pinfo,
                      epan_dissect_t *edt _U_, const void *data)
{
    follow_record_t *follow_record;
    follow_info_t *follow_info = (follow_info_t *)tapdata;
    tvbuff_t *next_tvb = (tvbuff_t *)data;

    follow_record = g_new(follow_record_t,1);

    follow_record->data = g_byte_array_sized_new(tvb_length(next_tvb));
    follow_record->data = g_byte_array_append(follow_record->data,
                                              tvb_get_ptr(next_tvb, 0, -1),
                                              tvb_length(next_tvb));

    if (follow_info->client_port == 0) {
        follow_info->client_port = pinfo->srcport;
        COPY_ADDRESS(&follow_info->client_ip, &pinfo->src);
    }

    if (ADDRESSES_EQUAL(&follow_info->client_ip, &pinfo->src) && follow_info->client_port == pinfo->srcport)
        follow_record->is_server = FALSE;
    else
        follow_record->is_server = TRUE;

    /* update stream counter */
Esempio n. 29
0
static int dissect_SuccessfulOutcomeValue(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  return (dissector_try_uint(sbc_ap_proc_sout_dissector_table, ProcedureCode, tvb, pinfo, tree)) ? tvb_length(tvb) : 0;
}
Esempio n. 30
0
/* Code to actually dissect the packets */
static int
dissect_lisp_data(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
    gint        offset = 0;
    guint8      flags;
    guint8      ip_ver;
    tvbuff_t   *next_tvb;
    proto_item *ti;
    proto_item *tif;
    proto_tree *lisp_data_tree;
    proto_tree *lisp_data_flags_tree;

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

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

    col_set_str(pinfo->cinfo, COL_INFO, "LISP Encapsulation Header");

    if (tree) {

        /* create display subtree for the protocol */
        ti = proto_tree_add_item(tree, proto_lisp_data, tvb, 0,
                LISP_DATA_HEADER_LEN, ENC_NA);

        lisp_data_tree = proto_item_add_subtree(ti, ett_lisp_data);

        tif = proto_tree_add_item(lisp_data_tree,
                hf_lisp_data_flags, tvb, offset, 1, ENC_BIG_ENDIAN);

        lisp_data_flags_tree = proto_item_add_subtree(tif, ett_lisp_data_flags);

        proto_tree_add_item(lisp_data_flags_tree,
                hf_lisp_data_flags_nonce, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(lisp_data_flags_tree,
                hf_lisp_data_flags_lsb, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(lisp_data_flags_tree,
                hf_lisp_data_flags_enr, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(lisp_data_flags_tree,
                hf_lisp_data_flags_mv, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(lisp_data_flags_tree,
                hf_lisp_data_flags_iid, tvb, offset, 1, ENC_BIG_ENDIAN);
        proto_tree_add_item(lisp_data_flags_tree,
                hf_lisp_data_flags_res, tvb, offset, 1, ENC_BIG_ENDIAN);

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

        if (flags&LISP_DATA_FLAG_E && !(flags&LISP_DATA_FLAG_N)) {
            proto_tree_add_text(lisp_data_tree, tvb, offset, 0,
                    "Invalid flag combination: if E is set, N MUST be set");
        }

        if (flags&LISP_DATA_FLAG_N) {
            if (flags&LISP_DATA_FLAG_V) {
                proto_tree_add_text(lisp_data_tree, tvb, offset, 0,
                        "Invalid flag combination: N and V can't be set both");
            }
            proto_tree_add_item(lisp_data_tree,
                    hf_lisp_data_nonce, tvb, offset, 3, ENC_BIG_ENDIAN);
        } else {
            if (flags&LISP_DATA_FLAG_V) {
                proto_item *tiv;
                proto_tree *lisp_data_mapver_tree;

                tiv = proto_tree_add_item(lisp_data_tree,
                        hf_lisp_data_mapver, tvb, offset, 3, ENC_BIG_ENDIAN);

                lisp_data_mapver_tree = proto_item_add_subtree(tiv, ett_lisp_data_mapver);

                proto_tree_add_item(lisp_data_mapver_tree,
                        hf_lisp_data_srcmapver, tvb, offset, 3, ENC_BIG_ENDIAN);
                proto_tree_add_item(lisp_data_mapver_tree,
                        hf_lisp_data_dstmapver, tvb, offset, 3, ENC_BIG_ENDIAN);
            }
        }
        offset += 3;

        if (flags&LISP_DATA_FLAG_I) {
            proto_tree_add_item(lisp_data_tree,
                    hf_lisp_data_iid, tvb, offset, 3, ENC_BIG_ENDIAN);
            offset += 3;
            if (flags&LISP_DATA_FLAG_L) {
                proto_tree_add_item(lisp_data_tree,
                        hf_lisp_data_lsb8, tvb, offset, 1, ENC_BIG_ENDIAN);
            }
            offset +=1;
        } else {
            if (flags&LISP_DATA_FLAG_L) {
                proto_tree_add_item(lisp_data_tree,
                        hf_lisp_data_lsb, tvb, offset, 4, ENC_BIG_ENDIAN);
                offset += 4;
            }
        }
    }

    /* Check if there is stuff left in the buffer, and return if not */

    /* Determine if encapsulated packet is IPv4 or IPv6, and call dissector */
    next_tvb = tvb_new_subset_remaining(tvb, LISP_DATA_HEADER_LEN);
    ip_ver = tvb_get_bits8(next_tvb, 0, 4);
    switch (ip_ver) {
        case 4:
            call_dissector(ipv4_handle, next_tvb, pinfo, tree);
            break;
        case 6:
            call_dissector(ipv6_handle, next_tvb, pinfo, tree);
            break;
        default:
            call_dissector(data_handle, next_tvb, pinfo, tree);
            break;
    }

    /* Return the amount of data this dissector was able to dissect */
    return tvb_length(tvb);
}