-/* packet-igmp.c 2001 Ronnie Sahlberg <rsahlber@bigpond.net.au>
+/* packet-igmp.c 2001 Ronnie Sahlberg <See AUTHORS for email>
* Routines for IGMP packet disassembly
*
- * $Id: packet-igmp.c,v 1.7 2001/06/29 18:55:49 guy Exp $
+ * $Id: packet-igmp.c,v 1.19 2002/05/02 07:54:41 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@ethereal.com>
* 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
#include <string.h>
#include <glib.h>
-#include "packet.h"
+#ifdef NEED_SNPRINTF_H
+# include "snprintf.h"
+#endif
+
+#include <epan/packet.h>
#include "ipproto.h"
#include "in_cksum.h"
#include "packet-dvmrp.h"
+#include "packet-pim.h"
#include "packet-mrdisc.h"
#include "packet-msnip.h"
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
#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_TRACEROUTE_RESPONSE 0x1e
+#define IGMP_TRACEROUTE_QUERY_REQ 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
+
static const value_string commands[] = {
{IGMP_V0_CREATE_GROUP_REQUEST, "Create Group Request" },
{IGMP_V0_CREATE_GROUP_REPLY, "Create Group Reply" },
{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_TRACEROUTE_RESPONSE, "Traceroute Response" },
+ {IGMP_TRACEROUTE_QUERY_REQ, "Traceroute Query or Request" },
{IGMP_V3_MEMBERSHIP_REPORT, "Membership Report" },
{0, NULL}
};
{ 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, \
+ if (check_col(pinfo->cinfo, COL_INFO)) { \
+ col_add_fstr(pinfo->cinfo, COL_INFO, \
"V%d %s",version,val_to_str(type, commands, \
"Unknown Type:0x%02x")); \
} \
proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type); \
offset += 1;
-static void igmp_checksum(proto_tree *tree,tvbuff_t *tvb, int len)
+void igmp_checksum(proto_tree *tree, tvbuff_t *tvb, int hf_index,
+ int hf_index_bad, packet_info *pinfo, guint len)
{
- guint16 cksum,hdrcksum;
+ guint16 cksum, hdrcksum;
vec_t cksum_vec[1];
- cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, len);
- cksum_vec[0].len = len;
+ if (len == 0) {
+ /*
+ * Checksum the entire IGMP packet.
+ */
+ len = tvb_reported_length(tvb);
+ }
hdrcksum = tvb_get_ntohs(tvb, 2);
- cksum = in_cksum(&cksum_vec[0],1);
+ if (!pinfo->fragmented && tvb_length(tvb) >= len) {
+ /*
+ * 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, len);
+ cksum_vec[0].len = len;
- if (cksum==0) {
- proto_tree_add_uint_format(tree, hf_checksum, tvb, 2, 2, hdrcksum, "Header checksum: 0x%04x (correct)", hdrcksum);
- } else {
- proto_tree_add_item_hidden(tree, hf_checksum_bad, tvb, 2, 2, TRUE);
- proto_tree_add_uint_format(tree, hf_checksum, tvb, 2, 2, hdrcksum, "Header checksum: 0x%04x (incorrect, should be 0x%04x)", hdrcksum,in_cksum_shouldbe(hdrcksum,cksum));
- }
+ cksum = in_cksum(&cksum_vec[0],1);
+
+ if (cksum == 0) {
+ proto_tree_add_uint_format(tree, hf_index,
+ tvb, 2, 2, hdrcksum,
+ "Header checksum: 0x%04x (correct)", hdrcksum);
+ } else {
+ proto_tree_add_boolean_hidden(tree, hf_index_bad,
+ tvb, 2, 2, TRUE);
+ proto_tree_add_uint_format(tree, hf_index,
+ tvb, 2, 2, hdrcksum,
+ "Header checksum: 0x%04x (incorrect, should be 0x%04x)", hdrcksum,in_cksum_shouldbe(hdrcksum,cksum));
+ }
+ } else
+ proto_tree_add_uint(tree, hf_index, tvb, 2, 2, hdrcksum);
return;
}
{
int len;
- if (check_col(pinfo->fd, COL_INFO)) {
- col_add_str(pinfo->fd, COL_INFO,
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_add_str(pinfo->cinfo, COL_INFO,
val_to_str(type, commands, "Unknown Type:0x%02x"));
}
* IGMP Protocol dissectors
*************************************************************/
static int
-dissect_v3_max_resp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+dissect_v3_max_resp(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
proto_tree *tree;
proto_item *item;
}
static int
-dissect_v3_sqrv_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+dissect_v3_sqrv_bits(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
proto_tree *tree;
proto_item *item;
}
static int
-dissect_v3_group_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
+dissect_v3_group_record(tvbuff_t *tvb, proto_tree *parent_tree, int offset)
{
proto_tree *tree;
proto_item *item;
guint16 num;
guint32 ip;
- ip = tvb_get_letohl(tvb, offset+4);
- item = proto_tree_add_text(parent_tree, tvb, offset, 0,
+ tvb_memcpy(tvb, (guint8 *)&ip, offset+4, 4);
+ item = proto_tree_add_text(parent_tree, tvb, offset, -1,
"Group Record : %s %s",
ip_to_str((gchar*)&ip),
val_to_str(tvb_get_guint8(tvb, offset), vs_record_type,"")
tree = proto_item_add_subtree(item, ett_group_record);
/* record type */
- proto_tree_add_uint(tree, hf_record_type, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ proto_tree_add_item(tree, hf_record_type, tvb, offset, 1, FALSE);
offset += 1;
/* aux data len */
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;
}
/* aux data */
if(adl){
- proto_tree_add_bytes(tree, hf_aux_data, tvb, offset, adl*4, tvb_get_ptr(tvb, offset, adl*4));
+ proto_tree_add_item(tree, hf_aux_data, tvb, offset, adl*4,
+ FALSE);
offset += adl*4;
}
offset += 1;
/* checksum */
- igmp_checksum(tree, tvb, pinfo->iplen-pinfo->iphdrlen*4);
- offset +=2;
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ offset += 2;
/* skip reserved field */
offset += 2;
offset += 2;
while (num--) {
- offset = dissect_v3_group_record(tvb,pinfo,tree,offset);
+ offset = dissect_v3_group_record(tvb, tree, offset);
}
return offset;
num = tvb_get_ntohs(tvb, offset+9);
/* max resp code */
- offset = dissect_v3_max_resp(tvb, pinfo, tree, offset);
+ offset = dissect_v3_max_resp(tvb, tree, offset);
/* checksum */
- igmp_checksum(tree, tvb, pinfo->iplen-pinfo->iphdrlen*4);
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
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 */
- offset = dissect_v3_sqrv_bits(tvb, pinfo, tree, offset);
+ offset = dissect_v3_sqrv_bits(tvb, tree, offset);
/* qqic */
- proto_tree_add_uint(tree, hf_qqic, tvb, offset, 1, tvb_get_guint8(tvb, offset));
+ proto_tree_add_item(tree, hf_qqic, tvb, offset, 1, FALSE);
offset += 1;
/*number of sources*/
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;
}
offset += 1;
/* checksum */
- igmp_checksum(tree, tvb, 8);
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 8);
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;
offset += 1;
/* checksum */
- igmp_checksum(tree, tvb, 8);
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 8);
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;
}
-/*
- * Dissector for V1 PIM messages.
- *
- * XXX - are these just PIM V1 messages (which we don't dissect in the PIM
- * dissector)? Where is PIM V1 documented? I'm inferring some of this
- * from the tcpdump IGMP dissector.
- */
-#define PIMV1_QUERY 0
-#define PIMV1_REGISTER 1
-#define PIMV1_REGISTER_STOP 2
-#define PIMV1_JOIN_PRUNE 3
-#define PIMV1_RP_REACHABLE 4
-#define PIMV1_ASSERT 5
-#define PIMV1_GRAFT 6
-#define PIMV1_GRAFT_ACK 7
-#define PIMV1_MODE 8
-
-static const value_string pim_routing_type[] = {
- { PIMV1_QUERY, "Query" },
- { PIMV1_REGISTER, "Register" },
- { PIMV1_REGISTER_STOP, "Register-Stop" },
- { PIMV1_JOIN_PRUNE, "Join/Prune" },
- { PIMV1_RP_REACHABLE, "RP-reachable" },
- { PIMV1_ASSERT, "Assert" },
- { PIMV1_GRAFT, "Graft" },
- { PIMV1_GRAFT_ACK, "Graft-ACK" },
- { PIMV1_MODE, "Mode" },
- { 0, NULL }
-};
-
-static int
-dissect_igmp_v1_pim_routing(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
-{
- guint8 pimv1_type;
-
- PRINT_IGMP_VERSION(1);
-
- pimv1_type = tvb_get_guint8(tvb, offset);
- proto_tree_add_text(tree, tvb, offset, 2, "Message type: %s",
- val_to_str(pimv1_type, pim_routing_type, "Unknown (%u)"));
-
- /* XXX - dissect the rest of it */
- return offset;
-}
-
/* dissector for version 0, rfc988 */
static int
dissect_igmp_v0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
offset += 1;
/* checksum */
- igmp_checksum(tree, tvb, 20);
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 20);
offset += 2;
/* identifier */
- proto_tree_add_uint(tree, hf_identifier, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
+ proto_tree_add_item(tree, hf_identifier, tvb, offset, 4, FALSE);
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 */
- proto_tree_add_bytes(tree, hf_access_key, tvb, offset, 8, tvb_get_ptr(tvb, offset, 8));
+ proto_tree_add_item(tree, hf_access_key, tvb, offset, 8, FALSE);
offset +=8;
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_reported_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_reported_length_remaining(tvb, offset) == IGMP_TRACEROUTE_HDR_LEN)
+ typestr = "Traceroute Query";
+ else
+ typestr = "Traceroute Request";
+
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_set_str(pinfo->cinfo, COL_INFO, typestr);
+ if (blocks) col_append_str(pinfo->cinfo, COL_INFO, blocks);
+ }
+
+ proto_tree_add_uint_format(tree, hf_type, tvb, offset, 1, type,
+ "Type: %s (0x%02x)", 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;
+
+ /* checksum */
+ igmp_checksum(tree, tvb, hf_checksum, hf_checksum_bad, pinfo, 0);
+ 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_reported_length_remaining(tvb, offset) == 0)
+ return offset;
+
+ /* Loop through the response data blocks */
+ while (tvb_reported_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)
{
unsigned char type;
guint32 dst;
- item = proto_tree_add_item(parent_tree, proto_igmp, tvb, offset, 0, FALSE);
+ item = proto_tree_add_item(parent_tree, proto_igmp, tvb, offset, -1, FALSE);
tree = proto_item_add_subtree(item, ett_igmp);
- if (check_col(pinfo->fd, COL_PROTOCOL)) {
- col_set_str(pinfo->fd, COL_PROTOCOL, "IGMP");
+ if (check_col(pinfo->cinfo, COL_PROTOCOL)) {
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGMP");
}
- if (check_col(pinfo->fd, COL_INFO)) {
- col_clear(pinfo->fd, COL_INFO);
+ if (check_col(pinfo->cinfo, COL_INFO)) {
+ col_clear(pinfo->cinfo, COL_INFO);
}
break;
case IGMP_V1_PIM_ROUTING_MESSAGE:
- offset = dissect_igmp_v1_pim_routing(tvb, pinfo, tree, type, offset);
+ offset = dissect_pimv1(tvb, pinfo, parent_tree, offset);
break;
case IGMP_V2_MEMBERSHIP_REPORT:
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:
offset = dissect_igmp_v3_response(tvb, pinfo, tree, type, offset);
break;
+
case IGMP_TYPE_0x23:
dst = htonl(MC_ALL_IGMPV3_ROUTERS);
if (!memcmp(pinfo->dst.data, &dst, 4)) {
offset = dissect_msnip(tvb, pinfo, parent_tree, offset);
}
break;
+
case IGMP_TYPE_0x24:
dst = htonl(MC_ALL_ROUTERS);
if (!memcmp(pinfo->dst.data, &dst, 4)) {
offset = dissect_msnip(tvb, pinfo, parent_tree, offset);
}
break;
+
case IGMP_TYPE_0x25:
if ( (pinfo->iplen-pinfo->iphdrlen*4)>=8 ) {
/* if len of igmp packet>=8 we assume it is MSNIP */
}
}
break;
+
case IGMP_TYPE_0x26:
dst = htonl(MC_ALL_ROUTERS);
if (!memcmp(pinfo->dst.data, &dst, 4)) {
{ "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,
+ { "Response 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",
void
proto_reg_handoff_igmp(void)
{
- dissector_add("ip.proto", IP_PROTO_IGMP, dissect_igmp, proto_igmp);
+ dissector_handle_t igmp_handle;
+
+ igmp_handle = create_dissector_handle(dissect_igmp, proto_igmp);
+ dissector_add("ip.proto", IP_PROTO_IGMP, igmp_handle);
}