Rewritten IGMP dissector, from Ronnie Sahlberg.

svn path=/trunk/; revision=3426
This commit is contained in:
Guy Harris 2001-05-20 22:20:33 +00:00
parent 281b8b2738
commit 724c494b70
5 changed files with 665 additions and 133 deletions

View File

@ -512,6 +512,7 @@ Ronnie Sahlberg <rsahlber@bigpond.net.au> {
rquota support completed
XDR array support
NIS+ support
Rewritten IGMP dissector
}
Borosa Tomislav <tomislav.borosa@SIEMENS.HR> {

View File

@ -1,7 +1,7 @@
# Makefile.am
# Automake file for Ethereal
#
# $Id: Makefile.am,v 1.319 2001/05/16 22:04:53 ashokn Exp $
# $Id: Makefile.am,v 1.320 2001/05/20 22:20:33 guy Exp $
#
# Ethereal - Network traffic analyzer
# By Gerald Combs <gerald@zing.org>
@ -119,6 +119,7 @@ DISSECTOR_SRC = \
packet-icmpv6.c\
packet-icp.c \
packet-icq.c \
packet-igmp.c \
packet-igrp.c \
packet-imap.c \
packet-ip.c \

View File

@ -1,7 +1,7 @@
## Makefile for building ethereal.exe with Microsoft C and nmake
## Use: $(MAKE) /$(MAKEFLAGS) -f makefile.nmake
#
# $Id: Makefile.nmake,v 1.105 2001/05/11 00:39:57 guy Exp $
# $Id: Makefile.nmake,v 1.106 2001/05/20 22:20:33 guy Exp $
include config.nmake
include <win32.mak>
@ -72,6 +72,7 @@ DISSECTOR_SRC = \
packet-icmpv6.c\
packet-icp.c \
packet-icq.c \
packet-igmp.c \
packet-igrp.c \
packet-imap.c \
packet-ip.c \

659
packet-igmp.c Normal file
View File

@ -0,0 +1,659 @@
/* packet-igmp.c 2001 Ronnie Sahlberg <rsahlber@bigpond.net.au>
* Routines for IGMP packet disassembly
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
* Copyright 1998 Gerald Combs
*
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*
IGMP is defined in the following RFCs
RFC988 Version 0 Obsolete
RFC1054 Version 1
RFC1112 Version 1 (same as RFC1054 as far as we are concerned)
RFC2236 Version 2
draft-ietf-idmr-igmp-v3-07 Version 3
Size in bytes for each packet
type RFC988 RFC1054 RFC2236 RFC????
v0 v1 v2 v3
0x01 20
0x02 20
0x03 20
0x04 20
0x05 20
0x06 20
0x07 20
0x08 20
0x11 8* 8* >=12
0x12 8* 8*
0x16 8
0x17 8
0x22 >=8
* Differs in second byte of protocol. Always 0 in V1
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_SYS_TYPES_H
# include <sys/types.h>
#endif
#include <stdio.h>
#include <string.h>
#include <glib.h>
#include "packet.h"
#include "ipproto.h"
#include "in_cksum.h"
static int proto_igmp = -1;
static int hf_type = -1;
static int hf_version = -1;
static int hf_group_type = -1;
static int hf_reply_code = -1;
static int hf_reply_pending = -1;
static int hf_checksum = -1;
static int hf_checksum_bad = -1;
static int hf_identifier = -1;
static int hf_access_key = -1;
static int hf_max_resp = -1;
static int hf_max_resp_exp = -1;
static int hf_max_resp_mant = -1;
static int hf_supress = -1;
static int hf_qrv = -1;
static int hf_qqic = -1;
static int hf_num_src = -1;
static int hf_saddr = -1;
static int hf_num_grp_recs = -1;
static int hf_record_type = -1;
static int hf_aux_data_len = -1;
static int hf_maddr = -1;
static int hf_aux_data = -1;
static int ett_igmp = -1;
static int ett_group_record = -1;
static int ett_sqrv_bits = -1;
static int ett_max_resp = -1;
#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_V2_MEMBERSHIP_REPORT 0x16
#define IGMP_V2_LEAVE_GROUP 0x17
#define IGMP_V3_MEMBERSHIP_REPORT 0x22
static const value_string commands[] = {
{IGMP_V0_CREATE_GROUP_REQUEST, "Create Group Request" },
{IGMP_V0_CREATE_GROUP_REPLY, "Create Group Reply" },
{IGMP_V0_JOIN_GROUP_REQUEST, "Join Group Request" },
{IGMP_V0_JOIN_GROUP_REPLY, "Join Group Reply" },
{IGMP_V0_LEAVE_GROUP_REQUEST, "Leave Group Request" },
{IGMP_V0_LEAVE_GROUP_REPLY, "Leave Group Reply" },
{IGMP_V0_CONFIRM_GROUP_REQUEST, "Confirm Group Request" },
{IGMP_V0_CONFIRM_GROUP_REPLY, "Confirm Group Reply" },
{IGMP_V1_HOST_MEMBERSHIP_QUERY, "Membership Query" },
{IGMP_V1_HOST_MEMBERSHIP_REPORT,"Membership Report" },
{IGMP_V2_MEMBERSHIP_REPORT, "Membership Report" },
{IGMP_V2_LEAVE_GROUP, "Leave Group" },
{IGMP_V3_MEMBERSHIP_REPORT, "Membership Report" },
{0, NULL}
};
#define IGMP_V3_S 0x08
#define IGMP_V3_QRV_MASK 0x07
#define IGMP_MAX_RESP_EXP 0x70
#define IGMP_MAX_RESP_MANT 0x0f
#define IGMP_V0_GROUP_PUBLIC 0x00
#define IGMP_V0_GROUP_PRIVATE 0x01
static const value_string vs_group_type[] = {
{IGMP_V0_GROUP_PUBLIC, "Public Group" },
{IGMP_V0_GROUP_PRIVATE, "Private Group" },
{0, NULL}
};
#define IGMP_V0_REPLY_GRANTED 0x00
#define IGMP_V0_REPLY_NO_RESOURCES 0x01
#define IGMP_V0_REPLY_INVALID_CODE 0x02
#define IGMP_V0_REPLY_INVALID_GROUP 0x03
#define IGMP_V0_REPLY_INVALID_KEY 0x04
static const value_string vs_reply_code[] = {
{IGMP_V0_REPLY_GRANTED, "Request Granted" },
{IGMP_V0_REPLY_NO_RESOURCES, "Request Denied, No Resources" },
{IGMP_V0_REPLY_INVALID_CODE, "Request Denied, Invalid Code" },
{IGMP_V0_REPLY_INVALID_GROUP, "Request Denied, Invalid Group" },
{IGMP_V0_REPLY_INVALID_KEY, "Request Denied, Invalid Key" },
{0, NULL}
};
static const true_false_string tfs_s = {
"SUPRESS router side processing",
"Do not supress router side processing"
};
#define IGMP_V3_MODE_IS_INCLUDE 1
#define IGMP_V3_MODE_IS_EXCLUDE 2
#define IGMP_V3_CHANGE_TO_INCLUDE_MODE 3
#define IGMP_V3_CHANGE_TO_EXCLUDE_MODE 4
#define IGMP_V3_ALLOW_NEW_SOURCES 5
#define IGMP_V3_BLOCK_OLD_SOURCES 6
static const value_string vs_record_type[] = {
{IGMP_V3_MODE_IS_INCLUDE, "Mode Is Include" },
{IGMP_V3_MODE_IS_EXCLUDE, "Mode Is Exclude" },
{IGMP_V3_CHANGE_TO_INCLUDE_MODE,"Change To Include Mode" },
{IGMP_V3_CHANGE_TO_EXCLUDE_MODE,"Change To Exclude Mode" },
{IGMP_V3_ALLOW_NEW_SOURCES, "Allow New Sources" },
{IGMP_V3_BLOCK_OLD_SOURCES, "Block Old Sources" },
{ 0, NULL}
};
#define PRINT_VERSION(version) \
if (check_col(pinfo->fd, COL_INFO)) { \
char str[256]; \
sprintf(str,"V%d %s",version,val_to_str(type, commands, \
"Unknown Type:0x%02x")); \
col_add_str(pinfo->fd, COL_INFO,str); \
} \
/* version of IGMP protocol */ \
proto_tree_add_uint(tree, hf_version, tvb, 0, 0, version); \
/* type of command */ \
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)
{
guint16 cksum,hdrcksum;
vec_t cksum_vec[1];
cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, len);
cksum_vec[0].len = len;
hdrcksum = tvb_get_ntohs(tvb, 2);
cksum = in_cksum(&cksum_vec[0],1);
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));
}
return;
}
static int
dissect_v3_max_resp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
{
proto_tree *tree;
proto_item *item;
guint8 bits;
guint32 tsecs;
bits = tvb_get_guint8(tvb, offset);
if (bits&0x80) {
tsecs = ((bits&IGMP_MAX_RESP_MANT)|0x10);
tsecs = tsecs << ( ((bits&IGMP_MAX_RESP_EXP)>>4) + 3);
} else {
tsecs = bits;
}
item = proto_tree_add_uint_format(parent_tree, hf_max_resp, tvb,
offset, 1, tsecs, "Max Response Time: %.1f sec (0x%02x)",tsecs*0.1,bits);
if (bits&0x80) {
tree = proto_item_add_subtree(item, ett_max_resp);
proto_tree_add_uint(tree, hf_max_resp_exp, tvb, offset, 1,
bits);
proto_tree_add_uint(tree, hf_max_resp_mant, tvb, offset, 1,
bits);
}
offset += 1;
return offset;
}
static int
dissect_v3_sqrv_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
{
proto_tree *tree;
proto_item *item;
guint8 bits;
bits = tvb_get_guint8(tvb, offset);
item = proto_tree_add_text(parent_tree, tvb, offset, 1,
"QRV=%d S=%s", bits&IGMP_V3_QRV_MASK,
(bits&IGMP_V3_S)?tfs_s.true_string:tfs_s.false_string);
tree = proto_item_add_subtree(item, ett_sqrv_bits);
/* S flag */
proto_tree_add_boolean(tree, hf_supress, tvb, offset, 1, bits);
/* QRV */
proto_tree_add_uint(tree, hf_qrv, tvb, offset, 1, bits);
offset += 1;
return offset;
}
static int
dissect_v3_group_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
{
proto_tree *tree;
proto_item *item;
int old_offset = offset;
guint8 adl;
guint16 num;
guint32 ip;
ip = tvb_get_letohl(tvb, offset+4);
item = proto_tree_add_text(parent_tree, tvb, offset, 0,
"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));
offset += 1;
/* aux data len */
adl = tvb_get_guint8(tvb, offset);
proto_tree_add_uint(tree, hf_aux_data_len, tvb, offset, 1, adl);
offset += 1;
/*number of sources*/
num = tvb_get_ntohs(tvb, offset);
proto_tree_add_uint(tree, hf_num_src, tvb, offset, 2, num);
offset += 2;
/* multicast address */
proto_tree_add_ipv4(tree, hf_maddr, tvb,
offset, 4, tvb_get_letohl(tvb, offset));
offset += 4;
/* source addresses */
while(num--){
proto_tree_add_ipv4(tree, hf_saddr, tvb,
offset, 4, tvb_get_letohl(tvb, offset));
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));
offset += adl*4;
}
proto_item_set_len(item, offset-old_offset);
return offset;
}
/* dissectors for version 3, rfc???? */
static int
dissect_igmp_v3_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
{
guint16 num;
PRINT_VERSION(3);
/* skip reserved field*/
offset += 1;
/* checksum */
igmp_checksum(tree, tvb, pinfo->iplen-pinfo->iphdrlen*4);
offset +=2;
/* skip reserved field */
offset += 2;
/* number of group records */
num = tvb_get_ntohs(tvb, offset);
proto_tree_add_uint(tree, hf_num_grp_recs, tvb, offset, 2, num);
offset += 2;
while (num--) {
offset = dissect_v3_group_record(tvb,pinfo,tree,offset);
}
return offset;
}
static int
dissect_igmp_v3_query(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
{
guint16 num;
PRINT_VERSION(3);
num = tvb_get_ntohs(tvb, offset+9);
/* max resp code */
offset = dissect_v3_max_resp(tvb, pinfo, tree, offset);
/* checksum */
igmp_checksum(tree, tvb, pinfo->iplen-pinfo->iphdrlen*4);
offset += 2;
/* group address */
proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, tvb_get_letohl(tvb, offset));
offset +=4;
/* bitmask for S and QRV */
offset = dissect_v3_sqrv_bits(tvb, pinfo, tree, offset);
/* qqic */
proto_tree_add_uint(tree, hf_qqic, tvb, offset, 1, tvb_get_guint8(tvb, offset));
offset += 1;
/*number of sources*/
proto_tree_add_uint(tree, hf_num_src, tvb, offset, 2, num);
offset += 2;
while(num--){
proto_tree_add_ipv4(tree, hf_saddr, tvb,
offset, 4, tvb_get_letohl(tvb, offset));
offset += 4;
}
return offset;
}
/* dissector for version 2, rfc2236 */
static int
dissect_igmp_v2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
{
guint8 tsecs;
PRINT_VERSION(2);
/* max resp time */
tsecs = tvb_get_guint8(tvb, offset);
proto_tree_add_uint_format(tree, hf_max_resp, tvb,
offset, 1, tsecs, "Max Response Time: %.1f sec (0x%02x)", tsecs*0.1,tsecs);
offset += 1;
/* checksum */
igmp_checksum(tree, tvb, 8);
offset += 2;
/* group address */
proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, tvb_get_letohl(tvb, offset));
offset +=4;
return offset;
}
/* dissector for version 1, rfc1054 */
static int
dissect_igmp_v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
{
PRINT_VERSION(1);
/* skip unused byte */
offset += 1;
/* checksum */
igmp_checksum(tree, tvb, 8);
offset += 2;
/* group address */
proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, tvb_get_letohl(tvb, offset));
offset +=4;
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)
{
unsigned char code;
PRINT_VERSION(0);
/* Code */
code = tvb_get_guint8(tvb, offset);
if (type==IGMP_V0_CREATE_GROUP_REQUEST) {
proto_tree_add_uint(tree, hf_group_type, tvb, offset, 1, code);
} else if (!(type&0x01)) {
if (code <5) {
proto_tree_add_uint(tree, hf_reply_code, tvb, offset, 1, code);
} else {
proto_tree_add_uint(tree, hf_reply_pending, tvb, offset, 1, code);
}
}
offset += 1;
/* checksum */
igmp_checksum(tree, tvb, 20);
offset += 2;
/* identifier */
proto_tree_add_uint(tree, hf_identifier, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
offset += 4;
/* group address */
proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, tvb_get_letohl(tvb, offset));
offset +=4;
/* access key */
proto_tree_add_bytes(tree, hf_access_key, tvb, offset, 8, tvb_get_ptr(tvb, offset, 8));
offset +=8;
return offset;
}
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;
item = proto_tree_add_item(parent_tree, proto_igmp, tvb, offset, 0, 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->fd, COL_INFO)) {
col_clear(pinfo->fd, COL_INFO);
}
type = tvb_get_guint8(tvb, offset);
/* version 0 */
if ((type&0xf0)==0){
offset = dissect_igmp_v0(tvb, pinfo, tree, type, offset);
}
/* 0x11 v1/v2/v3*/
if (type==0x11) {
/* version 3 */
if ( (pinfo->iplen-pinfo->iphdrlen*4)>=12 ) {
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)) {
offset = dissect_igmp_v2(tvb, pinfo, tree, type, offset);
} else {
offset = dissect_igmp_v1(tvb, pinfo, tree, type, offset);
}
}
}
/* 0x12 v1/v2*/
if (type==0x12) {
/* v1 and v2 differs in second byte of header */
if (tvb_get_guint8(tvb, offset)) {
offset = dissect_igmp_v2(tvb, pinfo, tree, type, offset);
} else {
offset = dissect_igmp_v1(tvb, pinfo, tree, type, offset);
}
}
/* 0x16 0x17 version 2*/
if((type==0x16)||(type==0x17)) {
offset = dissect_igmp_v2(tvb, pinfo, tree, type, offset);
}
/* 0x22 version 3 */
if (type==0x22) {
offset = dissect_igmp_v3_response(tvb, pinfo, tree, type, offset);
}
proto_item_set_len(item, offset);
}
void
proto_register_igmp(void)
{
static hf_register_info hf[] = {
{ &hf_type,
{ "Type", "igmp.type", FT_UINT8, BASE_HEX,
VALS(commands), 0, "IGMP Packet Type" }},
{ &hf_version,
{ "IGMP Version", "igmp.version", FT_UINT8, BASE_DEC,
NULL, 0, "IGMP Version" }},
{ &hf_group_type,
{ "Type Of Group", "igmp.group_type", FT_UINT8, BASE_DEC,
VALS(vs_group_type), 0, "IGMP V0 Type Of Group" }},
{ &hf_reply_code,
{ "Reply", "igmp.reply", FT_UINT8, BASE_DEC,
VALS(vs_reply_code), 0, "IGMP V0 Reply" }},
{ &hf_reply_pending,
{ "Reply Pending", "igmp.reply.pending", FT_UINT8, BASE_DEC,
NULL, 0, "IGMP V0 Reply Pending, Retry in this many seconds" }},
{ &hf_checksum,
{ "Checksum", "igmp.checksum", FT_UINT16, BASE_HEX,
NULL, 0, "IGMP Checksum" }},
{ &hf_checksum_bad,
{ "Bad Checksum", "igmp.checksum_bad", FT_BOOLEAN, BASE_NONE,
NULL, 0, "Bad IGMP Checksum" }},
{ &hf_identifier,
{ "Identifier", "igmp.identifier", FT_UINT32, BASE_DEC,
NULL, 0, "IGMP V0 Identifier" }},
{ &hf_access_key,
{ "Access Key", "igmp.access_key", FT_BYTES, BASE_HEX,
NULL, 0, "IGMP V0 Access Key" }},
{ &hf_max_resp,
{ "Max Resp Time", "igmp.max_resp", FT_UINT8, BASE_DEC,
NULL, 0, "Max Response Time" }},
{ &hf_supress,
{ "S", "igmp.s", FT_BOOLEAN, 8,
TFS(&tfs_s), IGMP_V3_S, "Supress Router Side Processing" }},
{ &hf_qrv,
{ "QRV", "igmp.qrv", FT_UINT8, BASE_DEC,
NULL, IGMP_V3_QRV_MASK, "Querier's Robustness Value"}},
{ &hf_qqic,
{ "QQIC", "igmp.qqic", FT_UINT8, BASE_DEC,
NULL, 0, "Querier's Query Interval Code" }},
{ &hf_num_src,
{ "Num Src", "igmp.num_src", FT_UINT16, BASE_DEC,
NULL, 0, "Number Of Sources" }},
{ &hf_saddr,
{ "Source Address", "igmp.saddr", FT_IPv4, BASE_NONE,
NULL, 0, "Source Address" }},
{ &hf_num_grp_recs,
{ "Num Group Records", "igmp.num_grp_recs", FT_UINT16, BASE_DEC,
NULL, 0, "Number Of Group Records" }},
{ &hf_record_type,
{ "Record Type", "igmp.record_type", FT_UINT8, BASE_DEC,
VALS(vs_record_type), 0, "Record Type"}},
{ &hf_aux_data_len,
{ "Aux Data Len", "igmp.aux_data_len", FT_UINT8, BASE_DEC,
NULL, 0, "Aux Data Len, In units of 32bit words"}},
{ &hf_maddr,
{ "Multicast Address", "igmp.maddr", FT_IPv4, BASE_NONE,
NULL, 0, "Multicast Address" }},
{ &hf_aux_data,
{ "Aux Data", "igmp.aux_data", FT_BYTES, BASE_HEX,
NULL, 0, "IGMP V3 Auxiliary Data" }},
{ &hf_max_resp_exp,
{ "Exponent", "igmp.max_resp.exp", FT_UINT8, BASE_HEX,
NULL, IGMP_MAX_RESP_EXP, "Maxmimum Response Time, Exponent"}},
{ &hf_max_resp_mant,
{ "Mantissa", "igmp.max_resp.mant", FT_UINT8, BASE_HEX,
NULL, IGMP_MAX_RESP_MANT, "Maxmimum Response Time, Mantissa"}},
};
static gint *ett[] = {
&ett_igmp,
&ett_group_record,
&ett_sqrv_bits,
&ett_max_resp,
};
proto_igmp = proto_register_protocol("Internet Group Management Protocol",
"IGMP", "igmp");
proto_register_field_array(proto_igmp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
void
proto_reg_handoff_igmp(void)
{
dissector_add("ip.proto", IP_PROTO_IGMP, dissect_igmp, proto_igmp);
}

View File

@ -1,7 +1,7 @@
/* packet-ip.c
* Routines for IP and miscellaneous IP protocol packet disassembly
*
* $Id: packet-ip.c,v 1.131 2001/04/18 04:53:51 guy Exp $
* $Id: packet-ip.c,v 1.132 2001/05/20 22:20:33 guy Exp $
*
* Ethereal - Network traffic analyzer
* By Gerald Combs <gerald@zing.org>
@ -58,7 +58,6 @@
#include "nlpid.h"
static void dissect_icmp(tvbuff_t *, packet_info *, proto_tree *);
static void dissect_igmp(tvbuff_t *, packet_info *, proto_tree *);
/* Decode the old IPv4 TOS field as the DiffServ DS Field */
static gboolean g_ip_dscp_actif = TRUE;
@ -114,15 +113,6 @@ static gint ett_ip_fragment = -1;
/* Used by IPv6 as well, so not static */
dissector_table_t ip_dissector_table;
static int proto_igmp = -1;
static int hf_igmp_version = -1;
static int hf_igmp_type = -1;
static int hf_igmp_unused = -1;
static int hf_igmp_checksum = -1;
static int hf_igmp_group = -1;
static gint ett_igmp = -1;
static int proto_icmp = -1;
static int hf_icmp_type = -1;
static int hf_icmp_code = -1;
@ -169,23 +159,6 @@ static gint ett_icmp = -1;
#define ICMP_PREC_CUTOFF 15 /* Precedence cut off */
/* IGMP structs and definitions */
typedef struct _e_igmp {
guint8 igmp_v_t; /* combines igmp_v and igmp_t */
guint8 igmp_unused;
guint16 igmp_cksum;
guint32 igmp_gaddr;
} e_igmp;
#define IGMP_M_QRY 0x01
#define IGMP_V1_M_RPT 0x02
#define IGMP_V2_LV_GRP 0x07
#define IGMP_DVMRP 0x03
#define IGMP_PIM 0x04
#define IGMP_V2_M_RPT 0x06
#define IGMP_MTRC_RESP 0x1e
#define IGMP_MTRC 0x1f
/* IP structs and definitions */
typedef struct _e_ip
@ -1720,109 +1693,6 @@ dissect_icmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
}
}
static void
dissect_igmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree)
{
e_igmp ih;
proto_tree *igmp_tree;
proto_item *ti;
gchar *type_str;
if (check_col(pinfo->fd, COL_PROTOCOL))
col_set_str(pinfo->fd, COL_PROTOCOL, "IGMP");
if (check_col(pinfo->fd, COL_INFO))
col_clear(pinfo->fd, COL_INFO);
/* Avoids alignment problems on many architectures. */
memcpy(&ih, tvb_get_ptr(tvb, 0, sizeof(e_igmp)), sizeof(e_igmp));
switch (lo_nibble(ih.igmp_v_t)) {
case IGMP_M_QRY:
type_str = "Router query";
break;
case IGMP_V1_M_RPT:
type_str = "Host response (v1)";
break;
case IGMP_V2_LV_GRP:
type_str = "Leave group (v2)";
break;
case IGMP_DVMRP:
type_str = "DVMRP";
break;
case IGMP_PIM:
type_str = "PIM";
break;
case IGMP_V2_M_RPT:
type_str = "Host response (v2)";
break;
case IGMP_MTRC_RESP:
type_str = "Traceroute response";
break;
case IGMP_MTRC:
type_str = "Traceroute message";
break;
default:
type_str = "Unknown IGMP";
}
if (check_col(pinfo->fd, COL_INFO))
col_add_str(pinfo->fd, COL_INFO, type_str);
if (tree) {
ti = proto_tree_add_item(tree, proto_igmp, tvb, 0, 8, FALSE);
igmp_tree = proto_item_add_subtree(ti, ett_igmp);
proto_tree_add_uint(igmp_tree, hf_igmp_version, tvb, 0, 1,
hi_nibble(ih.igmp_v_t));
proto_tree_add_uint_format(igmp_tree, hf_igmp_type, tvb, 0 , 1,
lo_nibble(ih.igmp_v_t),
"Type: %u (%s)",
lo_nibble(ih.igmp_v_t), type_str);
proto_tree_add_item(igmp_tree, hf_igmp_unused, tvb, 1, 1, FALSE);
proto_tree_add_item(igmp_tree, hf_igmp_checksum, tvb, 2, 2, FALSE);
proto_tree_add_ipv4(igmp_tree, hf_igmp_group, tvb, 4, 4, ih.igmp_gaddr);
}
}
void
proto_register_igmp(void)
{
static hf_register_info hf[] = {
{ &hf_igmp_version,
{ "Version", "igmp.version", FT_UINT8, BASE_DEC, NULL, 0x0,
"" }},
{ &hf_igmp_type,
{ "Type", "igmp.type", FT_UINT8, BASE_DEC, NULL, 0x0,
"" }},
{ &hf_igmp_unused,
{ "Unused", "igmp.unused", FT_UINT8, BASE_HEX, NULL, 0x0,
"" }},
{ &hf_igmp_checksum,
{ "Checksum", "igmp.checksum", FT_UINT16, BASE_HEX, NULL, 0x0,
"" }},
{ &hf_igmp_group,
{ "Group address", "igmp.group", FT_IPv4, BASE_NONE, NULL, 0x0,
"" }},
};
static gint *ett[] = {
&ett_igmp,
};
proto_igmp = proto_register_protocol("Internet Group Management Protocol",
"IGMP", "igmp");
proto_register_field_array(proto_igmp, hf, array_length(hf));
proto_register_subtree_array(ett, array_length(ett));
}
void
proto_reg_handoff_igmp(void)
{
dissector_add("ip.proto", IP_PROTO_IGMP, dissect_igmp, proto_igmp);
}
void
proto_register_ip(void)
{