Ethereal-dev: [Ethereal-dev] Patch: endian fixes and mtrace for packet-igmp.c

Note: This archive is from the project's previous web site, ethereal.com. This list is no longer active.

From: Heikki Vatiainen <hessu@xxxxxxxxx>
Date: 10 Jul 2001 21:34:34 +0300
This patch fixes a few endian problems with proto_tree_add_ipv4 by
changing them to proto_tree_add_item. The main part of patch is
a dissector for multicast traceroute packets.

There seem to be other dissectors too that have endian problems with
proto_tree_add_ipv4. I can try to locate them and change them to
proto_tree_add_item once I get the MSDP dissector done, which happens
hopefully this evening.

A sample mtrace is available at

http://atm.tut.fi/~hessu/ethereal/mtrace.cap 


Index: packet-igmp.c
===================================================================
RCS file: /cvsroot/ethereal/packet-igmp.c,v
retrieving revision 1.8
diff -u -r1.8 packet-igmp.c
--- packet-igmp.c	2001/07/02 09:23:02	1.8
+++ packet-igmp.c	2001/07/10 18:27:09
@@ -54,6 +54,15 @@
 
    * Differs in second byte of protocol. Always 0 in V1
 
+
+	Multicast traceroute was taken from
+	draft-ietf-idmr-traceroute-ipm-07.txt
+
+	Size in bytes for each packet
+	type    draft-ietf-idmr-traceroute-ipm-07.ps
+	0x1e      24 + n*32
+	0x1f      24 + n*32 (n == 0 for Query) 
+
    x DVMRP Protocol  see packet-dvmrp.c
 
 	DVMRP is defined in the following RFCs
@@ -122,11 +131,31 @@
 static int hf_aux_data_len = -1;
 static int hf_maddr = -1;
 static int hf_aux_data = -1;
+static int hf_mtrace_max_hops = -1;
+static int hf_mtrace_saddr = -1;
+static int hf_mtrace_raddr = -1;
+static int hf_mtrace_rspaddr = -1;
+static int hf_mtrace_resp_ttl = -1;
+static int hf_mtrace_q_id = -1;
+static int hf_mtrace_q_arrival = -1;
+static int hf_mtrace_q_inaddr = -1;
+static int hf_mtrace_q_outaddr = -1;
+static int hf_mtrace_q_prevrtr = -1;
+static int hf_mtrace_q_inpkt = -1;
+static int hf_mtrace_q_outpkt = -1;
+static int hf_mtrace_q_total = -1;
+static int hf_mtrace_q_rtg_proto = -1;
+static int hf_mtrace_q_fwd_ttl = -1;
+static int hf_mtrace_q_mbz = -1;
+static int hf_mtrace_q_s = -1;
+static int hf_mtrace_q_src_mask = -1;
+static int hf_mtrace_q_fwd_code = -1;
 
 static int ett_igmp = -1;
 static int ett_group_record = -1;
 static int ett_sqrv_bits = -1;
 static int ett_max_resp = -1;
+static int ett_mtrace_block = -1;
 
 #define MC_ALL_ROUTERS		0xe0000002
 #define MC_ALL_IGMPV3_ROUTERS	0xe0000016
@@ -146,14 +175,19 @@
 #define IGMP_V1_PIM_ROUTING_MESSAGE	0x14
 #define IGMP_V2_MEMBERSHIP_REPORT	0x16
 #define IGMP_V2_LEAVE_GROUP		0x17
-#define IGMP_V1_TRACEROUTE_RESPONSE	0x1e	/* XXX */
-#define IGMP_V1_TRACEROUTE_MESSAGE	0x1f	/* XXX */
+#define IGMP_V1_TRACEROUTE_RESPONSE	0x1e
+#define IGMP_V1_TRACEROUTE_MESSAGE	0x1f
 #define IGMP_V3_MEMBERSHIP_REPORT	0x22
 #define IGMP_TYPE_0x23			0x23
 #define IGMP_TYPE_0x24			0x24
 #define IGMP_TYPE_0x25			0x25
 #define IGMP_TYPE_0x26			0x26
 	
+#define IGMP_TRACEROUTE_HDR_LEN           24
+#define IGMP_TRACEROUTE_RSP_LEN           32
+#define IGMP_TRACEROUTE_RESPONSE        0x1e
+#define IGMP_TRACEROUTE_QUERY_REQ       0x1f
+
 static const value_string commands[] = {
 	{IGMP_V0_CREATE_GROUP_REQUEST,	"Create Group Request"		},
 	{IGMP_V0_CREATE_GROUP_REPLY,	"Create Group Reply"		},
@@ -169,8 +203,6 @@
 	{IGMP_V1_PIM_ROUTING_MESSAGE,	"PIM Routing Message"		},
 	{IGMP_V2_MEMBERSHIP_REPORT,	"Membership Report"		},
 	{IGMP_V2_LEAVE_GROUP,		"Leave Group"			},
-	{IGMP_V1_TRACEROUTE_RESPONSE,	"Traceroute Response"		},
-	{IGMP_V1_TRACEROUTE_MESSAGE,	"Traceroute Message"		},
 	{IGMP_V3_MEMBERSHIP_REPORT,	"Membership Report"		},
 	{0,		NULL}
 };
@@ -227,6 +259,40 @@
 	{ 0,	NULL}
 };
 
+static const value_string mtrace_rtg_vals[] = {
+	{1,  "DVMRP"                                        },
+	{2,  "MOSPF"                                        },
+	{3,  "PIM"                                          },
+	{4,  "CBT"                                          },
+	{5,  "PIM using special routing table"              },
+	{6,  "PIM using a static route"                     },
+	{7,  "DVMRP using a static route"                   },
+	{8,  "PIM using MBGP (aka BGP4+) route"             },
+	{9,  "CBT using special routing table"              },
+	{10, "CBT using a static route"                     },
+	{11, "PIM using state created by Assert processing" },
+        {0,  NULL}
+};
+
+static const value_string mtrace_fwd_code_vals[] = {
+	{0x00, "NO_ERROR"       },
+	{0x01, "WRONG_IF"       },
+	{0x02, "PRUNE_SENT"     },
+	{0x03, "PRUNE_RCVD"     },
+	{0x04, "SCOPED"         },
+	{0x05, "NO_ROUTE"       },
+	{0x06, "WRONG_LAST_HOP" },
+	{0x07, "NOT_FORWARDING" },
+	{0x08, "REACHED_RP"     },
+	{0x09, "RPF_IF"         },
+	{0x0A, "NO_MULTICAST"   },
+	{0x0B, "INFO_HIDDEN"    },
+	{0x81, "NO_SPACE"       },
+	{0x82, "OLD_ROUTER"     },
+	{0x83, "ADMIN_PROHIB"   },
+	{0, NULL}
+};
+
 #define PRINT_IGMP_VERSION(version) 					\
 	if (check_col(pinfo->fd, COL_INFO)) {				\
 		col_add_fstr(pinfo->fd, COL_INFO,			\
@@ -378,14 +444,12 @@
 	offset += 2;
 
 	/* multicast address */
-	proto_tree_add_ipv4(tree, hf_maddr, tvb, 
-		offset, 4, tvb_get_letohl(tvb, offset));
+	proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
 	offset += 4;
 
 	/* source addresses */
 	while(num--){
-		proto_tree_add_ipv4(tree, hf_saddr, tvb, 
-			offset, 4, tvb_get_letohl(tvb, offset));
+		proto_tree_add_item(tree, hf_saddr, tvb, offset, 4, FALSE);
 		offset += 4;
 	}
 
@@ -445,7 +509,7 @@
 	offset += 2;
 
 	/* group address */
-	proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+	proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
 	offset +=4;
 
 	/* bitmask for S and QRV */
@@ -460,8 +524,7 @@
 	offset += 2;
 
 	while(num--){
-		proto_tree_add_ipv4(tree, hf_saddr, tvb, 
-			offset, 4, tvb_get_letohl(tvb, offset));
+		proto_tree_add_item(tree, hf_saddr, tvb, offset, 4, FALSE);
 		offset += 4;
 	}
 
@@ -487,7 +550,7 @@
 	offset += 2;
 
 	/* group address */
-	proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+	proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
 	offset +=4;
 
 	return offset;
@@ -507,7 +570,7 @@
 	offset += 2;
 
 	/* group address */
-	proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+	proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
 	offset +=4;
 
 	return offset;
@@ -543,7 +606,7 @@
 	offset += 4;
 
 	/* group address */
-	proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, tvb_get_letohl(tvb, offset));
+	proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
 	offset +=4;
 
 	/* access key */
@@ -553,6 +616,141 @@
 	return offset;		
 } 
 
+/* dissector for multicast traceroute, rfc???? */
+static int
+dissect_igmp_mtrace(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+{
+	char *typestr, *blocks = NULL;
+	char buf[20];
+
+	/* All multicast traceroute packets (Query, Request and
+	 * Response) have the same fixed header. Request and Response
+	 * have one or more response data blocks following this fixed
+	 * header. Since Query and Request share the same IGMP type,
+	 * the method to differentiate between them is to check the
+	 * IGMP packet length. Queries are only
+	 * IGMP_TRACEROUTE_HDR_LEN bytes long.
+	 */
+	if (type == IGMP_TRACEROUTE_RESPONSE) {
+		int i = (tvb_length_remaining(tvb, offset) - IGMP_TRACEROUTE_HDR_LEN) / IGMP_TRACEROUTE_RSP_LEN;
+		snprintf(buf, sizeof buf, ", %d block%s", i, plurality(i, "", "s"));
+		typestr = "Traceroute Response";
+		blocks = buf;
+	} else if (tvb_length_remaining(tvb, offset) == IGMP_TRACEROUTE_HDR_LEN)
+		typestr = "Traceroute Query";
+	else
+		typestr = "Traceroute Request";
+
+	if (check_col(pinfo->fd, COL_INFO)) {
+		col_set_str(pinfo->fd, COL_INFO, typestr);
+		if (blocks) col_append_str(pinfo->fd, COL_INFO, blocks);
+	}
+
+	/* First add hidden for filtering, then add text for display purposes */
+	proto_tree_add_uint_hidden(tree, hf_type, tvb, offset, 1, type);
+	proto_tree_add_text(tree, tvb, offset, 1, "Type: %s (0x%x)", typestr, type);
+	offset += 1;
+
+	/* maximum number of hops that the requester wants to trace */
+	proto_tree_add_item(tree, hf_mtrace_max_hops, tvb, offset, 1, FALSE);
+	offset += 1;
+
+	/* - 2 since the checksum covers the whole IGMP packet (the entire IP payload) */
+	igmp_checksum(tree, tvb, tvb_length_remaining(tvb, offset - 2));
+	offset += 2;
+
+	/* group address to be traced */
+	proto_tree_add_item(tree, hf_maddr, tvb, offset, 4, FALSE);
+	offset += 4;
+
+	/* address of multicast source for the path being traced */
+	proto_tree_add_item(tree, hf_mtrace_saddr, tvb, offset, 4, FALSE);
+	offset += 4;
+
+	/* address of multicast receiver for the path being traced */
+	proto_tree_add_item(tree, hf_mtrace_raddr, tvb, offset, 4, FALSE);
+	offset += 4;
+
+	/* address where the completed traceroute response packet gets sent */
+	proto_tree_add_item(tree, hf_mtrace_rspaddr, tvb, offset, 4, FALSE);
+	offset += 4;
+
+	/* for multicasted responses, TTL at which to multicast the response */
+	proto_tree_add_item(tree, hf_mtrace_resp_ttl, tvb, offset, 1, FALSE);
+	offset += 1;
+
+	/* unique identifier for this traceroute request (for e.g. duplicate/delay detection) */
+	proto_tree_add_item(tree, hf_mtrace_q_id, tvb, offset, 3, FALSE);
+	offset += 3;
+
+	/* If this was Query, we only had the fixed header */
+	if (tvb_length_remaining(tvb, offset) == 0)
+		return offset;
+
+	/* Loop through the response data blocks */
+        while (tvb_length_remaining(tvb, offset) >= IGMP_TRACEROUTE_RSP_LEN) {
+                proto_item *bi;
+                proto_tree *block_tree;
+
+                bi = proto_tree_add_text(tree, tvb, offset, IGMP_TRACEROUTE_RSP_LEN,
+                                         "Response data block: %s -> %s,  Proto: %s,  Forwarding Code: %s",
+                                         ip_to_str(tvb_get_ptr(tvb, offset + 4, 4)),
+                                         ip_to_str(tvb_get_ptr(tvb, offset + 8, 4)),
+                                         val_to_str(tvb_get_guint8(tvb, offset + 28), mtrace_rtg_vals, "Unknown"),
+                                         val_to_str(tvb_get_guint8(tvb, offset + 31), mtrace_fwd_code_vals, "Unknown"));
+                block_tree = proto_item_add_subtree(bi, ett_mtrace_block);
+
+		/* Query Arrival Time */
+		proto_tree_add_item(block_tree, hf_mtrace_q_arrival, tvb, offset, 4, FALSE);
+		offset += 4;
+
+		/* Incoming Interface Address */
+		proto_tree_add_item(block_tree, hf_mtrace_q_inaddr, tvb, offset, 4, FALSE);
+		offset += 4;
+
+		/* Outgoing Interface Address */
+		proto_tree_add_item(block_tree, hf_mtrace_q_outaddr, tvb, offset, 4, FALSE);
+		offset += 4;
+
+		/* Previous-Hop Router Address */
+		proto_tree_add_item(block_tree, hf_mtrace_q_prevrtr, tvb, offset, 4, FALSE);
+		offset += 4;
+
+		/* Input packet count on incoming interface */
+		proto_tree_add_item(block_tree, hf_mtrace_q_inpkt, tvb, offset, 4, FALSE);
+		offset += 4;
+
+		/* Output packet count on outgoing interface */
+		proto_tree_add_item(block_tree, hf_mtrace_q_outpkt, tvb, offset, 4, FALSE);
+		offset += 4;
+
+		/* Total number of packets for this source-group pair */
+		proto_tree_add_item(block_tree, hf_mtrace_q_total, tvb, offset, 4, FALSE);
+		offset += 4;
+
+		/* Routing protocol in use between this and previous-hop router */
+		proto_tree_add_item(block_tree, hf_mtrace_q_rtg_proto, tvb, offset, 1, FALSE);
+		offset += 1;
+
+		/* TTL that a packet is required to be forwarded */
+		proto_tree_add_item(block_tree, hf_mtrace_q_fwd_ttl, tvb, offset, 1, FALSE);
+		offset += 1;
+
+		/* Must be zeroed and ignored bit, S bit and src network mask length */
+		proto_tree_add_item(block_tree, hf_mtrace_q_mbz, tvb, offset, 1, FALSE);
+		proto_tree_add_item(block_tree, hf_mtrace_q_s, tvb, offset, 1, FALSE);
+		proto_tree_add_item(block_tree, hf_mtrace_q_src_mask, tvb, offset, 1, FALSE);
+		offset += 1;
+
+		/* Forwarding information/error code */
+		proto_tree_add_item(block_tree, hf_mtrace_q_fwd_code, tvb, offset, 1, FALSE);	
+		offset += 1;
+	}
+
+
+	return offset;
+}
+
 static void
 dissect_igmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
 {
@@ -621,22 +819,9 @@
 		offset = dissect_igmp_v2(tvb, pinfo, tree, type, offset);
 		break;
 
-	case IGMP_V1_TRACEROUTE_RESPONSE:
-		/* XXX - V1 or V2? */
-		offset = dissect_igmp_v1(tvb, pinfo, tree, type, offset);
-		/*
-		 * XXX - dissect the rest as traceroute response; see the
-		 * tcpdump IGMP dissector.
-		 */
-		break;
-
-	case IGMP_V1_TRACEROUTE_MESSAGE:
-		/* XXX - V1 or V2? */
-		offset = dissect_igmp_v1(tvb, pinfo, tree, type, offset);
-		/*
-		 * XXX - dissect the rest as traceroute message; see the
-		 * tcpdump IGMP dissector.
-		 */
+	case IGMP_TRACEROUTE_RESPONSE:
+	case IGMP_TRACEROUTE_QUERY_REQ:
+		offset = dissect_igmp_mtrace(tvb, pinfo, tree, type, offset);
 		break;
 
 	case IGMP_V3_MEMBERSHIP_REPORT:
@@ -782,12 +967,89 @@
 			{ "Mantissa", "igmp.max_resp.mant", FT_UINT8, BASE_HEX,
 			NULL, IGMP_MAX_RESP_MANT, "Maxmimum Response Time, Mantissa", HFILL }},
 
+		{ &hf_mtrace_max_hops,
+			{ "# hops", "igmp.mtrace.max_hops", FT_UINT8, BASE_DEC,
+			NULL, 0, "Maxmimum Number of Hops to Trace", HFILL }},
+
+		{ &hf_mtrace_saddr,
+			{ "Source Address", "igmp.mtrace.saddr", FT_IPv4, BASE_NONE,
+			  NULL, 0, "Multicast Source for the Path Being Traced", HFILL }},
+
+		{ &hf_mtrace_raddr,
+			{ "Receiver Address", "igmp.mtrace.raddr", FT_IPv4, BASE_NONE,
+			  NULL, 0, "Multicast Receiver for the Path Being Traced", HFILL }},
+
+		{ &hf_mtrace_rspaddr,
+			{ "Response Address", "igmp.mtrace.rspaddr", FT_IPv4, BASE_NONE,
+			  NULL, 0, "Destination of Completed Traceroute Response", HFILL }},
+
+		{ &hf_mtrace_resp_ttl,
+			{ "resp ttl", "igmp.mtrace.resp_ttl", FT_UINT8, BASE_DEC,
+			NULL, 0, "TTL for Multicasted Responses", HFILL }},
+
+		{ &hf_mtrace_q_id,
+			{ "Query ID", "igmp.mtrace.q_id", FT_UINT24, BASE_DEC,
+			NULL, 0, "Identifier for this Traceroute Request", HFILL }},
+
+		{ &hf_mtrace_q_arrival,
+			{ "Query Arrival", "igmp.mtrace.q_arrival", FT_UINT32, BASE_DEC,
+			NULL, 0, "Query Arrival Time", HFILL }},
+
+		{ &hf_mtrace_q_inaddr,
+			{ "In itf addr", "igmp.mtrace.q_inaddr", FT_IPv4, BASE_NONE,
+			NULL, 0, "Incoming Interface Address", HFILL }},
+
+		{ &hf_mtrace_q_outaddr,
+			{ "Out itf addr", "igmp.mtrace.q_outaddr", FT_IPv4, BASE_NONE,
+			NULL, 0, "Outgoing Interface Address", HFILL }},
+
+		{ &hf_mtrace_q_prevrtr,
+			{ "Previous rtr addr", "igmp.mtrace.q_prevrtr", FT_IPv4, BASE_NONE,
+			NULL, 0, "Previous-Hop Router Address", HFILL }},
+
+		{ &hf_mtrace_q_inpkt,
+			{ "In pkts", "igmp.mtrace.q_inpkt", FT_UINT32, BASE_DEC,
+			NULL, 0, "Input packet count on incoming interface", HFILL }},
+
+		{ &hf_mtrace_q_outpkt,
+			{ "Out pkts", "igmp.mtrace.q_outpkt", FT_UINT32, BASE_DEC,
+			NULL, 0, "Output packet count on outgoing interface", HFILL }},
+
+		{ &hf_mtrace_q_total,
+			{ "S,G pkt count", "igmp.mtrace.q_total", FT_UINT32, BASE_DEC,
+			NULL, 0, "Total number of packets for this source-group pair", HFILL }},
+
+		{ &hf_mtrace_q_rtg_proto,
+			{ "Rtg Protocol", "igmp.mtrace.q_rtg_proto", FT_UINT8, BASE_DEC,
+			VALS(&mtrace_rtg_vals), 0, "Routing protocol between this and previous hop rtr", HFILL }},
+
+		{ &hf_mtrace_q_fwd_ttl,
+			{ "FwdTTL", "igmp.mtrace.q_fwd_ttl", FT_UINT8, BASE_DEC,
+			NULL, 0, "TTL required for forwarding", HFILL }},
+
+		{ &hf_mtrace_q_mbz,
+			{ "MBZ", "igmp.mtrace.q_mbz", FT_UINT8, BASE_HEX,
+			NULL, 0x80, "Must be zeroed on transmission and ignored on reception", HFILL }},
+
+		{ &hf_mtrace_q_s,
+			{ "S", "igmp.mtrace.q_s", FT_UINT8, BASE_HEX,
+			NULL, 0x40, "Set if S,G packet count is for source network", HFILL }},
+
+		{ &hf_mtrace_q_src_mask,
+			{ "Src Mask", "igmp.mtrace.q_src_mask", FT_UINT8, BASE_HEX,
+			NULL, 0x3F, "Source mask length. 63 when forwarding on group state", HFILL }},
+
+		{ &hf_mtrace_q_fwd_code,
+			{ "Forwarding Code", "igmp.mtrace.q_fwd_code", FT_UINT8, BASE_HEX,
+			VALS(&mtrace_fwd_code_vals), 0, "Forwarding information/error code", HFILL }},
+
 	};
 	static gint *ett[] = {
 		&ett_igmp,
 		&ett_group_record,
 		&ett_sqrv_bits,
 		&ett_max_resp,
+		&ett_mtrace_block,
 	};
 
 	proto_igmp = proto_register_protocol("Internet Group Management Protocol",


-- 
Heikki Vatiainen                  * hessu@xxxxxxxxx
Tampere University of Technology  * Tampere, Finland