Пример #1
0
static void
dissect_epmd_response(ptvcursor_t *cursor)
{
    tvbuff_t *tvb;
    guint32 port;
    guint8 type;

    tvb = ptvcursor_tvbuff(cursor);
    port = tvb_get_ntohl(tvb, 0);
    if (port == EPMD_PORT) {
	dissect_epmd_response_names(cursor);
	return;
    }

    type = tvb_get_guint8(tvb, 0);
    ptvcursor_add(cursor, hf_epmd_type, 1, FALSE);
    switch (type) {
	case EPMD_PORT_PLEASE2_OK: {
	    ptvcursor_advance(cursor, 1);
/* 'w', 0, Port(16), Type(8), Proto(8), High(16), Low(16), NLen(16), Name(x) */
	    ptvcursor_add(cursor, hf_epmd_tcp_port, 2, FALSE);
	    ptvcursor_advance(cursor, 2); /* 'M', 0 */
	    ptvcursor_add(cursor, hf_epmd_dist_high, 2, FALSE);
	    ptvcursor_add(cursor, hf_epmd_dist_low, 2, FALSE);
	    ptvcursor_add(cursor, hf_epmd_name_len, 2, FALSE);
	    ptvcursor_add(cursor, hf_epmd_name, -1, FALSE);
	}
	case EPMD_ALIVE_OK:
	case EPMD_ALIVE2_OK: {
	    ptvcursor_add(cursor, hf_epmd_result, 1, FALSE);
	    ptvcursor_add(cursor, hf_epmd_creation, 2, FALSE);
	}
	default:
	    break;
    }
}
Пример #2
0
static void
dissect_epmd_request(ptvcursor_t *cursor)
{
    tvbuff_t *tvb;
    guint8 type;

    tvb = ptvcursor_tvbuff(cursor);
    ptvcursor_add(cursor, hf_epmd_len, 2, FALSE);

    type = tvb_get_guint8(tvb, ptvcursor_current_offset(cursor));
    ptvcursor_add(cursor, hf_epmd_type, 1, FALSE);
    switch (type) {
	case EPMD_ALIVE2: {
	    guint16 name_length, elen;
	    ptvcursor_add(cursor, hf_epmd_tcp_port, 2, FALSE);
	    ptvcursor_advance(cursor,2); /* 'M', 0 */
	    ptvcursor_add(cursor, hf_epmd_dist_high, 2, FALSE);
	    ptvcursor_add(cursor, hf_epmd_dist_low, 2, FALSE);
	    name_length = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
	    ptvcursor_add(cursor, hf_epmd_name_len, 2, FALSE);
	    ptvcursor_add(cursor, hf_epmd_name, name_length, FALSE);
	    elen = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
	    ptvcursor_add(cursor, hf_epmd_elen, 2, FALSE);
	    if (elen > 0)
		ptvcursor_add(cursor, hf_epmd_edata, elen, FALSE);
	    break;
	}
	case EPMD_PORT_PLEASE:
	case EPMD_PORT_PLEASE2:
	    /*ptvcursor_add(cursor, hf_epmd_name, tvb_length(tvb)-3, FALSE);*/
	    ptvcursor_add(cursor, hf_epmd_name, -1, FALSE);
	    break;
	case EPMD_ALIVE: {
	    ptvcursor_add(cursor, hf_epmd_tcp_port, 2, FALSE);
	    /*ptvcursor_add(cursor, hf_epmd_name, tvb_length(tvb)-3, FALSE);*/
	    ptvcursor_add(cursor, hf_epmd_name, -1, FALSE);
	    break;
	}
	case EPMD_NAMES:
	default:
	    break;
    }
}
Пример #3
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);
	}
}
Пример #4
0
static void
dissect_pgmopts(ptvcursor_t* cursor, const char *pktname)
{
	proto_item *tf;
	proto_tree *opts_tree = NULL;
	proto_tree *opt_tree = NULL;
	tvbuff_t *tvb = ptvcursor_tvbuff(cursor);

	gboolean theend = FALSE;

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

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

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

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

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

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

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

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

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

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

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

			break;
		}
		case PGM_OPT_PARITY_PRM:{
			guint8 optdata_po;

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

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


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

			ptvcursor_add(cursor, hf_pgm_opt_parity_prm_prmtgsz, 4, ENC_BIG_ENDIAN);

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

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

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

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

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

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

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

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

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

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

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

			switch (optdata_afi) {

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

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

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

			break;
		}
		case PGM_OPT_PGMCC_FEEDBACK:{
			guint16 optdata_afi;

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

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

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

			switch (optdata_afi) {

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

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

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

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

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

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

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

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

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

			break;
		}
		case PGM_OPT_REDIRECT:{
			guint16 optdata_afi;

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

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

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

			switch (optdata_afi) {

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

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

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

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

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

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

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

		opts_total_len -= genopts_len;
	}
	return;
}
Пример #5
0
static void
dissect_omapi(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
  proto_item *ti;
  proto_tree *omapi_tree;
  ptvcursor_t* cursor;

  guint32 authlength;
  guint32 msglength;
  guint32 objlength;


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

  col_clear(pinfo->cinfo, COL_INFO);

  ti = proto_tree_add_item(tree, proto_omapi, tvb, 0, -1, ENC_NA);
  omapi_tree = proto_item_add_subtree(ti, ett_omapi);
  cursor = ptvcursor_new(omapi_tree, tvb, 0);

  if (tvb_reported_length_remaining(tvb, 0) < 8)
  {
    /* Payload too small for OMAPI */
    DISSECTOR_ASSERT_NOT_REACHED();
  }
  else if (tvb_reported_length_remaining(tvb, 0) < 24)
  {
    /* This is a startup message */
    ptvcursor_add(cursor, hf_omapi_version, 4, ENC_BIG_ENDIAN);
    ptvcursor_add(cursor, hf_omapi_hlength, 4, ENC_BIG_ENDIAN);

    col_set_str(pinfo->cinfo, COL_INFO, "Status message");
    proto_item_append_text(ti, ", Status message");

    return;
  }
  else if ( !(tvb_get_ntohl(tvb, 8) || tvb_get_ntohl(tvb, 12)) )
  {
    /* This is a startup message, and more */
    ptvcursor_add(cursor, hf_omapi_version, 4, ENC_BIG_ENDIAN);
    ptvcursor_add(cursor, hf_omapi_hlength, 4, ENC_BIG_ENDIAN);

    col_append_str(pinfo->cinfo, COL_INFO, "Status message");

    proto_item_append_text(ti, ", Status message");
  }

  ptvcursor_add(cursor, hf_omapi_auth_id, 4, ENC_BIG_ENDIAN);
  authlength = tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor));
  ptvcursor_add(cursor, hf_omapi_auth_len, 4, ENC_BIG_ENDIAN);

  col_append_sep_str(pinfo->cinfo, COL_INFO, NULL,
      val_to_str(tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)), omapi_opcode_vals, "Unknown opcode (0x%04x)"));

  proto_item_append_text(ti, ", Opcode: %s",
    val_to_str(tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor)), omapi_opcode_vals, "Unknown opcode (0x%04x)"));

  ptvcursor_add(cursor, hf_omapi_opcode, 4, ENC_BIG_ENDIAN);
  ptvcursor_add(cursor, hf_omapi_handle, 4, ENC_BIG_ENDIAN);
  ptvcursor_add(cursor, hf_omapi_id, 4, ENC_BIG_ENDIAN);
  ptvcursor_add(cursor, hf_omapi_rid, 4, ENC_BIG_ENDIAN);

  msglength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
  while (msglength)
  {
    ptvcursor_add(cursor, hf_omapi_msg_name_len, 2, ENC_BIG_ENDIAN);
    ptvcursor_add(cursor, hf_omapi_msg_name, msglength, ENC_ASCII|ENC_NA);
    msglength = tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor));
    ptvcursor_add(cursor, hf_omapi_msg_value_len, 4, ENC_BIG_ENDIAN);

    if (msglength == 0)
    {
      proto_tree_add_text(omapi_tree, tvb, 0, 0, "Empty string");
    }
    else if (msglength == (guint32)~0)
    {
      proto_tree_add_text(omapi_tree, tvb, 0, 0, "No value");
    }
    else
    {
      ptvcursor_add(cursor, hf_omapi_msg_value, msglength, ENC_ASCII|ENC_NA);
    }

    msglength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
  }

  proto_tree_add_text(omapi_tree, tvb, ptvcursor_current_offset(cursor), 2, "Message end tag");
  ptvcursor_advance(cursor, 2);

  objlength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
  while (objlength)
  {
    ptvcursor_add(cursor, hf_omapi_obj_name_len, 2, ENC_BIG_ENDIAN);
    ptvcursor_add(cursor, hf_omapi_obj_name, objlength, ENC_ASCII|ENC_NA);
    objlength = tvb_get_ntohl(tvb, ptvcursor_current_offset(cursor));
    ptvcursor_add(cursor, hf_omapi_obj_value_len, 4, ENC_BIG_ENDIAN);

    if (objlength == 0)
    {
      proto_tree_add_text(omapi_tree, tvb, 0, 0, "Empty string");
    }
    else if (objlength == (guint32)~0)
    {
      proto_tree_add_text(omapi_tree, tvb, 0, 0, "No value");
    }
    else
    {
      ptvcursor_add(cursor, hf_omapi_obj_value, objlength, ENC_NA);
    }

    objlength = tvb_get_ntohs(tvb, ptvcursor_current_offset(cursor));
  }

  proto_tree_add_text(omapi_tree, tvb, ptvcursor_current_offset(cursor), 2, "Object end tag");
  ptvcursor_advance(cursor, 2);

  if (authlength > 0) {
    ptvcursor_add(cursor, hf_omapi_signature, authlength, ENC_NA);
  }
}