/*
 Zebra Protocol header version 0:
	0                   1                   2                   3
	0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	+-------------------------------+---------------+
	|           Length (2)          |   Command (1) |
	+-------------------------------+---------------+

 Zebra Protocol header version 1:
	0                   1                   2                   3
	0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	+-------------------------------+---------------+-------------+
	|           Length (2)          |   Marker (1)  | Version (1) |
	+-------------------------------+---------------+-------------+
	|          Command (2)          |
	+-------------------------------+
 The Marker is 0xFF to distinguish it from a version 0 header.
 */
static void
dissect_zebra(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item	*ti;
	proto_tree	*zebra_tree;
	gboolean	request;
	int		left, offset;

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

	request = (pinfo->destport == pinfo->match_uint);
	left = tvb_reported_length(tvb);
	offset = 0;

	col_set_str(pinfo->cinfo, COL_INFO,
		    request? "Zebra Request" : "Zebra Reply");

	/* if (tree) */ {
		ti = proto_tree_add_item(tree, proto_zebra, tvb, offset, -1,
					 ENC_NA);
		zebra_tree = proto_item_add_subtree(ti, ett_zebra);
		ti = proto_tree_add_boolean(zebra_tree, hf_zebra_request,
					    tvb, offset, 0, request);
		PROTO_ITEM_SET_HIDDEN(ti);

		for (;;) {
			guint8 		headermarker, version;
			guint16		command, len;
			proto_tree	*zebra_request_tree;

			if (left < 3)
				break;
			len = tvb_get_ntohs(tvb, offset);
			if (len < 3)
				break;

			headermarker = tvb_get_guint8(tvb,offset+2);
			if (headermarker != 0xFF) {
				command = headermarker;
				version = 0;
			} else {
				version = tvb_get_guint8(tvb, offset+3);
				command = tvb_get_ntohs(tvb, offset+4);
			}
			col_append_fstr(pinfo->cinfo, COL_INFO, ": %s",
				val_to_str(command, messages, "Command Type 0x%02d"));
			ti = proto_tree_add_uint(zebra_tree,
						 hf_zebra_command, tvb,
						 offset, len, command);
			zebra_request_tree = proto_item_add_subtree(ti,
							ett_zebra_request);
			dissect_zebra_request(zebra_request_tree, request, tvb,
					      offset, len, command, version);
			offset += len;
			left -= len;
		}
	}
}
static void
dissect_zebra(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
	proto_item	*ti;
	proto_tree	*zebra_tree;
	gboolean	request;
	int		left, offset;

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

	request = (pinfo->destport == pinfo->match_uint);
	left = tvb_reported_length(tvb);
	offset = 0;

	if (check_col(pinfo->cinfo, COL_INFO)) {
		col_set_str(pinfo->cinfo, COL_INFO,
			request? "ZEBRA Request" : "ZEBRA Reply");
	}
	if (tree) {
		ti = proto_tree_add_item(tree, proto_zebra, tvb, offset, -1,
			ENC_NA);
		zebra_tree = proto_item_add_subtree(ti, ett_zebra);
		ti = proto_tree_add_boolean(zebra_tree, hf_zebra_request,
			tvb, offset, 0, request);
		PROTO_ITEM_SET_HIDDEN(ti);

		for (;;) {
			guint8		command;
			guint16		len;
			proto_tree	*zebra_request_tree;

			if (left < 3) break;

			len = tvb_get_ntohs(tvb, offset);
			if (len < 3) break;

			command = tvb_get_guint8(tvb, offset+2);

			ti = proto_tree_add_uint(zebra_tree,
				hf_zebra_command, tvb, offset, len,
				command);
			zebra_request_tree = proto_item_add_subtree(ti,
				ett_zebra_request);
			dissect_zebra_request(zebra_request_tree, request, tvb,
				offset, len, command);

			offset += len;
			left -= len;
		}
	}
}