aboutsummaryrefslogtreecommitdiffstats
path: root/epan/dissectors/packet-igmp.c
diff options
context:
space:
mode:
authorMichael Mann <mmann78@netscape.net>2014-11-07 07:47:43 -0500
committerMichael Mann <mmann78@netscape.net>2014-11-08 16:33:50 +0000
commit421913b721d5b12c1f6c8a09daec35d8bae58bb5 (patch)
tree1c039d5db023456f106d3bd1d221401463639daf /epan/dissectors/packet-igmp.c
parentbd5384c84a53a88c64fb79094444c063756ca183 (diff)
Create real subdissectors to the IGMP protocol.
Change-Id: I79ee9413b87722bfe4782342737cff03cfc34495 Reviewed-on: https://code.wireshark.org/review/5179 Petri-Dish: Michael Mann <mmann78@netscape.net> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com> Reviewed-by: Michael Mann <mmann78@netscape.net>
Diffstat (limited to 'epan/dissectors/packet-igmp.c')
-rw-r--r--epan/dissectors/packet-igmp.c321
1 files changed, 139 insertions, 182 deletions
diff --git a/epan/dissectors/packet-igmp.c b/epan/dissectors/packet-igmp.c
index 3ce05e6bfa..968aba7f29 100644
--- a/epan/dissectors/packet-igmp.c
+++ b/epan/dissectors/packet-igmp.c
@@ -112,16 +112,11 @@
#include <glib.h>
#include <epan/packet.h>
+#include <epan/range.h>
#include <epan/to_str.h>
#include <epan/ipproto.h>
#include <epan/in_cksum.h>
#include "packet-igmp.h"
-#include "packet-dvmrp.h"
-#include "packet-pim.h"
-#include "packet-mrdisc.h"
-#include "packet-msnip.h"
-#include "packet-igap.h"
-#include "packet-rgmp.h"
void proto_register_igmp(void);
void proto_reg_handoff_igmp(void);
@@ -176,32 +171,7 @@ 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 MC_RGMP 0xe0000019
-
-
-#define IGMP_V0_CREATE_GROUP_REQUEST 0x01
-#define IGMP_V0_CREATE_GROUP_REPLY 0x02
-#define IGMP_V0_JOIN_GROUP_REQUEST 0x03
-#define IGMP_V0_JOIN_GROUP_REPLY 0x04
-#define IGMP_V0_LEAVE_GROUP_REQUEST 0x05
-#define IGMP_V0_LEAVE_GROUP_REPLY 0x06
-#define IGMP_V0_CONFIRM_GROUP_REQUEST 0x07
-#define IGMP_V0_CONFIRM_GROUP_REPLY 0x08
-#define IGMP_V1_HOST_MEMBERSHIP_QUERY 0x11
-#define IGMP_V1_HOST_MEMBERSHIP_REPORT 0x12
-#define IGMP_DVMRP 0x13
-#define IGMP_V1_PIM_ROUTING_MESSAGE 0x14
-#define IGMP_V2_MEMBERSHIP_REPORT 0x16
-#define IGMP_V2_LEAVE_GROUP 0x17
-#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
+static dissector_table_t subdissector_table;
#define IGMP_TRACEROUTE_HDR_LEN 24
#define IGMP_TRACEROUTE_RSP_LEN 32
@@ -313,20 +283,6 @@ static const value_string mtrace_fwd_code_vals[] = {
{0, NULL}
};
-#define PRINT_IGMP_VERSION(version) \
- do { \
- proto_item *ti; \
- col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "IGMPv%d",version); \
- col_add_fstr(pinfo->cinfo, COL_INFO, \
- "%s",val_to_str(type, commands, "Unknown Type:0x%02x")); \
- /* version of IGMP protocol */ \
- ti = proto_tree_add_uint(tree, hf_version, tvb, 0, 0, version); \
- PROTO_ITEM_SET_GENERATED(ti); \
- /* type of command */ \
- proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type);\
- offset += 1; \
- } while (0);
-
void igmp_checksum(proto_tree *tree, tvbuff_t *tvb, int hf_index,
int hf_index_bad, packet_info *pinfo, guint len)
{
@@ -368,13 +324,50 @@ void igmp_checksum(proto_tree *tree, tvbuff_t *tvb, int hf_index,
return;
}
+static proto_tree*
+dissect_igmp_common(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int* offset, unsigned char* type, int version)
+{
+ proto_item* ti;
+ proto_tree* igmp_tree;
+
+ col_add_fstr(pinfo->cinfo, COL_PROTOCOL, "IGMPv%d", version);
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ ti = proto_tree_add_item(tree, proto_igmp, tvb, 0, -1, ENC_NA);
+ igmp_tree = proto_item_add_subtree(ti, ett_igmp);
+
+ *type = tvb_get_guint8(tvb, 0);
+ col_add_fstr(pinfo->cinfo, COL_INFO, "%s", val_to_str(*type, commands, "Unknown Type:0x%02x"));
+
+ /* version of IGMP protocol */
+ ti = proto_tree_add_uint(igmp_tree, hf_version, tvb, 0, 0, version);
+ PROTO_ITEM_SET_GENERATED(ti);
+
+ /* type of command */
+ proto_tree_add_item(igmp_tree, hf_type, tvb, 0, 1, ENC_NA);
+ *offset = 1;
+
+ return igmp_tree;
+}
+
/* Unknown IGMP message type */
static int
-dissect_igmp_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+dissect_igmp_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
+ proto_item* ti;
+ proto_tree* tree;
int len;
+ int offset = 0;
+ unsigned char type;
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGMP");
+ col_clear(pinfo->cinfo, COL_INFO);
+
+ ti = proto_tree_add_item(parent_tree, proto_igmp, tvb, offset, -1, ENC_NA);
+ tree = proto_item_add_subtree(ti, ett_igmp);
+ type = tvb_get_guint8(tvb, offset);
col_add_str(pinfo->cinfo, COL_INFO,
val_to_str(type, commands, "Unknown Type:0x%02x"));
@@ -565,11 +558,14 @@ dissect_v3_group_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tr
/* dissectors for version 3, rfc3376 */
static int
-dissect_igmp_v3_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+dissect_igmp_v3_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
{
+ proto_tree* tree;
guint16 num;
+ int offset;
+ unsigned char type;
- PRINT_IGMP_VERSION(3);
+ tree = dissect_igmp_common(tvb, pinfo, parent_tree, &offset, &type, 3);
/* skip reserved field*/
offset += 1;
@@ -596,12 +592,15 @@ dissect_igmp_v3_report(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int
}
static int
-dissect_igmp_v3_query(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+dissect_igmp_v3_query(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
{
+ proto_tree* tree;
guint16 num;
guint32 maddr;
+ int offset;
+ unsigned char type;
- PRINT_IGMP_VERSION(3);
+ tree = dissect_igmp_common(tvb, pinfo, parent_tree, &offset, &type, 3);
num = tvb_get_ntohs(tvb, offset+9);
/* max resp code */
@@ -648,12 +647,15 @@ dissect_igmp_v3_query(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int t
/* dissector for version 2 query and report, rfc2236 */
static int
-dissect_igmp_v2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+dissect_igmp_v2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
{
+ proto_tree* tree;
guint8 tsecs;
guint32 maddr;
+ int offset;
+ unsigned char type;
- PRINT_IGMP_VERSION(2);
+ tree = dissect_igmp_common(tvb, pinfo, parent_tree, &offset, &type, 2);
/* max resp time */
tsecs = tvb_get_guint8(tvb, offset);
@@ -672,15 +674,17 @@ dissect_igmp_v2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, i
if (! maddr) {
col_append_str(pinfo->cinfo, COL_INFO, ", general");
} else {
- if (type == IGMP_V2_LEAVE_GROUP) {
- col_append_fstr(pinfo->cinfo, COL_INFO,
- " %s", ip_to_str((guint8*)&maddr));
- } else if (type == IGMP_V1_HOST_MEMBERSHIP_QUERY) {
- col_append_fstr(pinfo->cinfo, COL_INFO,
- ", specific for group %s", ip_to_str((guint8*)&maddr));
- } else { /* IGMP_V2_MEMBERSHIP_REPORT is the only case left */
- col_append_fstr(pinfo->cinfo, COL_INFO,
- " group %s", ip_to_str((guint8*)&maddr));
+ switch(type)
+ {
+ case IGMP_V2_LEAVE_GROUP:
+ col_append_fstr(pinfo->cinfo, COL_INFO, " %s", ip_to_str((guint8*)&maddr));
+ break;
+ case IGMP_V1_HOST_MEMBERSHIP_QUERY:
+ col_append_fstr(pinfo->cinfo, COL_INFO, ", specific for group %s", ip_to_str((guint8*)&maddr));
+ break;
+ default: /* IGMP_V2_MEMBERSHIP_REPORT is the only case left */
+ col_append_fstr(pinfo->cinfo, COL_INFO, " group %s", ip_to_str((guint8*)&maddr));
+ break;
}
}
offset +=4;
@@ -690,9 +694,13 @@ dissect_igmp_v2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, i
/* dissector for version 1 query and report, rfc1054 */
static int
-dissect_igmp_v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+dissect_igmp_v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
{
- PRINT_IGMP_VERSION(1);
+ proto_tree* tree;
+ int offset;
+ unsigned char type;
+
+ tree = dissect_igmp_common(tvb, pinfo, parent_tree, &offset, &type, 1);
/* skip unused byte */
offset += 1;
@@ -710,11 +718,14 @@ dissect_igmp_v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, i
/* dissector for version 0, rfc988 */
static int
-dissect_igmp_v0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+dissect_igmp_v0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
{
+ proto_tree* tree;
unsigned char code;
+ int offset;
+ unsigned char type;
- PRINT_IGMP_VERSION(0);
+ tree = dissect_igmp_common(tvb, pinfo, parent_tree, &offset, &type, 0);
/* Code */
code = tvb_get_guint8(tvb, offset);
@@ -748,13 +759,39 @@ dissect_igmp_v0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, i
return offset;
}
+static int
+dissect_igmp_mquery(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data)
+{
+ if ( tvb_reported_length(tvb)>=12 ) {
+ /* version 3 */
+ return dissect_igmp_v3_query(tvb, pinfo, parent_tree, data);
+ }
+
+ /* v1 and v2 differs in second byte of header */
+ if (tvb_get_guint8(tvb, 1)) {
+ return dissect_igmp_v2(tvb, pinfo, parent_tree, data);
+ }
+
+ return dissect_igmp_v1(tvb, pinfo, parent_tree, data);
+}
+
/* dissector for multicast traceroute, rfc???? */
static int
-dissect_igmp_mtrace(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
+dissect_igmp_mtrace(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U_)
{
+ proto_tree* tree;
+ proto_item* ti;
+ int offset = 0;
+ unsigned char type;
const char *typestr, *blocks = NULL;
char buf[20];
+ ti = proto_tree_add_item(parent_tree, proto_igmp, tvb, offset, -1, ENC_NA);
+ tree = proto_item_add_subtree(ti, ett_igmp);
+
+ col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGMP");
+ col_clear(pinfo->cinfo, COL_INFO);
+
/* 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
@@ -763,6 +800,7 @@ dissect_igmp_mtrace(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int typ
* IGMP packet length. Queries are only
* IGMP_TRACEROUTE_HDR_LEN bytes long.
*/
+ type = tvb_get_guint8(tvb, offset);
if (type == IGMP_TRACEROUTE_RESPONSE) {
int i = (tvb_reported_length_remaining(tvb, offset) - IGMP_TRACEROUTE_HDR_LEN) / IGMP_TRACEROUTE_RSP_LEN;
g_snprintf(buf, sizeof buf, ", %d block%s", i, plurality(i, "", "s"));
@@ -881,126 +919,15 @@ dissect_igmp_mtrace(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int typ
static void
dissect_igmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
{
- proto_tree *tree;
- proto_item *item;
int offset = 0;
unsigned char type;
- guint32 dst;
-
- item = proto_tree_add_item(parent_tree, proto_igmp, tvb, offset, -1, ENC_NA);
- tree = proto_item_add_subtree(item, ett_igmp);
-
- col_set_str(pinfo->cinfo, COL_PROTOCOL, "IGMP");
- col_clear(pinfo->cinfo, COL_INFO);
type = tvb_get_guint8(tvb, offset);
- /* version 0 */
- if ((type&0xf0)==0){
- offset = dissect_igmp_v0(tvb, pinfo, tree, type, offset);
+ if (!dissector_try_uint(subdissector_table, type, tvb, pinfo, parent_tree))
+ {
+ dissect_igmp_unknown(tvb, pinfo, parent_tree);
}
-
- switch (type) {
- case IGMP_V1_HOST_MEMBERSHIP_QUERY: /* 0x11 v1/v2/v3 */
- if ( tvb_reported_length(tvb)>=12 ) {
- /* version 3 */
- offset = dissect_igmp_v3_query(tvb, pinfo, tree, type, offset);
- } else {
- /* v1 and v2 differs in second byte of header */
- if (tvb_get_guint8(tvb, offset+1)) {
- offset = dissect_igmp_v2(tvb, pinfo, tree, type, offset);
- } else {
- offset = dissect_igmp_v1(tvb, pinfo, tree, type, offset);
- }
- }
- break;
-
- case IGMP_V1_HOST_MEMBERSHIP_REPORT: /* 0x12 v1 only */
- offset = dissect_igmp_v1(tvb, pinfo, tree, type, offset);
- break;
-
- case IGMP_DVMRP:
- offset = dissect_dvmrp(tvb, pinfo, parent_tree, offset);
- break;
-
- case IGMP_V1_PIM_ROUTING_MESSAGE:
- offset = dissect_pimv1(tvb, pinfo, parent_tree, offset);
- break;
-
- case IGMP_V2_MEMBERSHIP_REPORT:
- case IGMP_V2_LEAVE_GROUP:
- offset = dissect_igmp_v2(tvb, pinfo, tree, type, offset);
- break;
-
- 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_report(tvb, pinfo, tree, type, offset);
- break;
-
- case IGMP_TYPE_0x23:
- dst = g_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 = g_htonl(MC_ALL_ROUTERS);
- if (!memcmp(pinfo->dst.data, &dst, 4)) {
- offset = dissect_mrdisc(tvb, pinfo, parent_tree, offset);
- }
- dst = g_htonl(MC_ALL_IGMPV3_ROUTERS);
- if (!memcmp(pinfo->dst.data, &dst, 4)) {
- offset = dissect_msnip(tvb, pinfo, parent_tree, offset);
- }
- break;
-
- case IGMP_TYPE_0x25:
- if ( tvb_reported_length(tvb)>=8 ) {
- /* if len of igmp packet>=8 we assume it is MSNIP */
- offset = dissect_msnip(tvb, pinfo, parent_tree, offset);
- } else {
- /* ok it's not MSNIP, check if it might be MRDISC */
- dst = g_htonl(MC_ALL_ROUTERS);
- if (!memcmp(pinfo->dst.data, &dst, 4)) {
- offset = dissect_mrdisc(tvb, pinfo, parent_tree, offset);
- }
- }
- break;
-
- case IGMP_TYPE_0x26:
- dst = g_htonl(MC_ALL_ROUTERS);
- if (!memcmp(pinfo->dst.data, &dst, 4)) {
- offset = dissect_mrdisc(tvb, pinfo, parent_tree, offset);
- }
- break;
-
- case IGMP_IGAP_JOIN:
- case IGMP_IGAP_QUERY:
- case IGMP_IGAP_LEAVE:
- offset = dissect_igap(tvb, pinfo, parent_tree, offset);
- break;
-
- case IGMP_RGMP_HELLO:
- case IGMP_RGMP_BYE:
- case IGMP_RGMP_JOIN:
- case IGMP_RGMP_LEAVE:
- dst = g_htonl(MC_RGMP);
- if (!memcmp(pinfo->dst.data, &dst, 4)) {
- offset = dissect_rgmp(tvb, pinfo, parent_tree, offset);
- }
- break;
-
- default:
- offset = dissect_igmp_unknown(tvb, pinfo, tree, type, offset);
- break;
- }
-
- proto_item_set_len(item, offset);
}
void
@@ -1188,15 +1115,45 @@ proto_register_igmp(void)
"IGMP", "igmp");
proto_register_field_array(proto_igmp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
+
+ subdissector_table = register_dissector_table("igmp.type", "IGMP commands", FT_UINT32, BASE_HEX);
+
}
void
proto_reg_handoff_igmp(void)
{
- dissector_handle_t igmp_handle;
+ dissector_handle_t igmp_handle, igmpv0_handle, igmpv1_handle, igmpv2_handle,
+ igmp_mquery_handle, igmp_mtrace_handle, igmp_report_handle;
+ range_t *igmpv0_range;
igmp_handle = create_dissector_handle(dissect_igmp, proto_igmp);
dissector_add_uint("ip.proto", IP_PROTO_IGMP, igmp_handle);
+
+ /* IGMP v0 */
+ range_convert_str(&igmpv0_range, "0-15", 15);
+ igmpv0_handle = new_create_dissector_handle(dissect_igmp_v0, proto_igmp);
+ dissector_add_uint_range("igmp.type", igmpv0_range, igmpv0_handle);
+
+ /* IGMP v1 */
+ igmpv1_handle = new_create_dissector_handle(dissect_igmp_v1, proto_igmp);
+ dissector_add_uint("igmp.type", IGMP_V1_HOST_MEMBERSHIP_REPORT, igmpv1_handle);
+
+ /* IGMP v2 */
+ igmpv2_handle = new_create_dissector_handle(dissect_igmp_v2, proto_igmp);
+ dissector_add_uint("igmp.type", IGMP_V2_MEMBERSHIP_REPORT, igmpv2_handle);
+ dissector_add_uint("igmp.type", IGMP_V2_LEAVE_GROUP, igmpv2_handle);
+
+ /* IGMP_V1_HOST_MEMBERSHIP_QUERY, all versions */
+ igmp_mquery_handle = new_create_dissector_handle(dissect_igmp_mquery, proto_igmp);
+ dissector_add_uint("igmp.type", IGMP_V1_HOST_MEMBERSHIP_QUERY, igmp_mquery_handle);
+
+ igmp_report_handle = new_create_dissector_handle(dissect_igmp_v3_report, proto_igmp);
+ dissector_add_uint("igmp.type", IGMP_V3_MEMBERSHIP_REPORT, igmp_report_handle);
+
+ igmp_mtrace_handle = new_create_dissector_handle(dissect_igmp_mtrace, proto_igmp);
+ dissector_add_uint("igmp.type", IGMP_TRACEROUTE_RESPONSE, igmp_mtrace_handle);
+ dissector_add_uint("igmp.type", IGMP_TRACEROUTE_QUERY_REQ, igmp_mtrace_handle);
}
/*