2001-05-20 22:20:33 +00:00
/* packet-igmp.c 2001 Ronnie Sahlberg <rsahlber@bigpond.net.au>
* Routines for IGMP packet disassembly
*
2001-07-10 20:55:54 +00:00
* $ Id : packet - igmp . c , v 1.9 2001 / 07 / 10 20 : 55 : 54 guy Exp $
2001-06-12 06:21:55 +00:00
*
2001-05-20 22:20:33 +00:00
* Ethereal - Network traffic analyzer
2001-05-25 18:44:01 +00:00
* By Gerald Combs < gerald @ ethereal . com >
2001-05-20 22:20:33 +00:00
* 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
2001-06-29 18:55:50 +00:00
type RFC988 RFC1054 RFC2236 RFC ? ? ? ? DVMRP MRDISC MSNIP
2001-06-12 06:21:55 +00:00
v0 v1 v2 v3 v1 / v3
2001-05-20 22:20:33 +00:00
0x01 20
0x02 20
0x03 20
0x04 20
0x05 20
0x06 20
0x07 20
0x08 20
0x11 8 * 8 * > = 12
0x12 8 * 8 *
2001-06-12 06:21:55 +00:00
0x13 x
2001-05-20 22:20:33 +00:00
0x16 8
0x17 8
0x22 > = 8
2001-06-29 18:55:50 +00:00
0x23 > = 8 b
0x24 > = 8 a 8 b
0x25 4 a > = 8 b
0x26 4 a
2001-06-27 20:19:19 +00:00
2001-05-20 22:20:33 +00:00
* Differs in second byte of protocol . Always 0 in V1
2001-06-12 06:21:55 +00:00
2001-07-10 20:55:54 +00:00
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 )
2001-06-27 20:19:19 +00:00
x DVMRP Protocol see packet - dvmrp . c
2001-06-12 06:21:55 +00:00
DVMRP is defined in the following RFCs
RFC1075 Version 1
draft - ietf - idmr - dvmrp - v3 - 10. txt Version 3
V1 and V3 can be distinguished by looking at bytes 6 and 7 in the
IGMP header .
If header [ 6 ] = = 0xff and header [ 7 ] = = 0x03 we have version 3.
2001-06-27 20:19:19 +00:00
a MRDISC Protocol see packet - mrdisc . c
MRDISC : IGMP Multicast Router DISCovery
draft - ietf - idmr - igmp - mrdisc - 06. txt
TTL = = 1 and IP . DST = = 224.0 .0 .2 for all packets
2001-06-29 18:55:50 +00:00
b MSNIP Protocol see packet - msnip . c
MSNIP : Multicast Source Notification of Interest Protocol
draft - ietf - idmr - msnip - 00. txt
0x23 , 0x24 are sent with ip . dst = = 224.0 .0 .22
0x25 is sent as unicast .
2001-05-20 22:20:33 +00:00
*/
# 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"
2001-06-12 06:21:55 +00:00
# include "packet-dvmrp.h"
2001-07-02 09:23:02 +00:00
# include "packet-pim.h"
2001-06-27 20:19:19 +00:00
# include "packet-mrdisc.h"
2001-06-29 18:55:50 +00:00
# include "packet-msnip.h"
2001-05-20 22:20:33 +00:00
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 ;
2001-07-10 20:55:54 +00:00
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 ;
2001-05-20 22:20:33 +00:00
static int ett_igmp = - 1 ;
static int ett_group_record = - 1 ;
static int ett_sqrv_bits = - 1 ;
static int ett_max_resp = - 1 ;
2001-07-10 20:55:54 +00:00
static int ett_mtrace_block = - 1 ;
2001-05-20 22:20:33 +00:00
2001-06-29 18:55:50 +00:00
# define MC_ALL_ROUTERS 0xe0000002
# define MC_ALL_IGMPV3_ROUTERS 0xe0000016
2001-06-27 20:19:19 +00:00
2001-05-20 22:20:33 +00:00
# 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
2001-06-12 06:21:55 +00:00
# define IGMP_DVMRP 0x13
2001-05-25 06:47:02 +00:00
# define IGMP_V1_PIM_ROUTING_MESSAGE 0x14
2001-05-20 22:20:33 +00:00
# define IGMP_V2_MEMBERSHIP_REPORT 0x16
# define IGMP_V2_LEAVE_GROUP 0x17
2001-07-10 20:55:54 +00:00
# define IGMP_V1_TRACEROUTE_RESPONSE 0x1e
# define IGMP_V1_TRACEROUTE_MESSAGE 0x1f
2001-05-20 22:20:33 +00:00
# define IGMP_V3_MEMBERSHIP_REPORT 0x22
2001-06-29 18:55:50 +00:00
# define IGMP_TYPE_0x23 0x23
2001-06-27 20:19:19 +00:00
# define IGMP_TYPE_0x24 0x24
# define IGMP_TYPE_0x25 0x25
# define IGMP_TYPE_0x26 0x26
2001-05-20 22:20:33 +00:00
2001-07-10 20:55:54 +00:00
# define IGMP_TRACEROUTE_HDR_LEN 24
# define IGMP_TRACEROUTE_RSP_LEN 32
# define IGMP_TRACEROUTE_RESPONSE 0x1e
# define IGMP_TRACEROUTE_QUERY_REQ 0x1f
2001-05-20 22:20:33 +00:00
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 " } ,
2001-06-12 06:21:55 +00:00
{ IGMP_DVMRP , " DVMRP Protocol " } ,
2001-05-25 06:47:02 +00:00
{ IGMP_V1_PIM_ROUTING_MESSAGE , " PIM Routing Message " } ,
2001-05-20 22:20:33 +00:00
{ 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 }
} ;
2001-07-10 20:55:54 +00:00
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 }
} ;
2001-06-12 06:21:55 +00:00
# define PRINT_IGMP_VERSION(version) \
2001-05-20 22:20:33 +00:00
if ( check_col ( pinfo - > fd , COL_INFO ) ) { \
2001-05-25 18:44:01 +00:00
col_add_fstr ( pinfo - > fd , COL_INFO , \
" V%d %s " , version , val_to_str ( type , commands , \
2001-05-20 22:20:33 +00:00
" Unknown Type:0x%02x " ) ) ; \
} \
/* 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 ;
}
2001-05-25 18:44:01 +00:00
/* Unknown IGMP message type */
static int
dissect_igmp_unknown ( tvbuff_t * tvb , packet_info * pinfo , proto_tree * tree , int type , int offset )
{
int len ;
if ( check_col ( pinfo - > fd , COL_INFO ) ) {
col_add_str ( pinfo - > fd , COL_INFO ,
val_to_str ( type , commands , " Unknown Type:0x%02x " ) ) ;
}
/* type of command */
proto_tree_add_uint ( tree , hf_type , tvb , offset , 1 , type ) ;
offset + = 1 ;
/* Just call the rest of it "data" */
len = tvb_length_remaining ( tvb , offset ) ;
proto_tree_add_text ( tree , tvb , offset , len , " Data " ) ;
offset + = len ;
return offset ;
}
2001-06-12 06:21:55 +00:00
/*************************************************************
* IGMP Protocol dissectors
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2001-05-20 22:20:33 +00:00
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 ;
2001-07-10 20:55:54 +00:00
tvb_memcpy ( tvb , ( guint8 * ) & ip , offset + 4 , 4 ) ;
2001-05-20 22:20:33 +00:00
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 */
2001-07-10 20:55:54 +00:00
proto_tree_add_item ( tree , hf_record_type , tvb , offset , 1 , FALSE ) ;
2001-05-20 22:20:33 +00:00
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 */
2001-07-10 20:55:54 +00:00
proto_tree_add_item ( tree , hf_maddr , tvb , offset , 4 , FALSE ) ;
2001-05-20 22:20:33 +00:00
offset + = 4 ;
/* source addresses */
while ( num - - ) {
2001-07-10 20:55:54 +00:00
proto_tree_add_item ( tree , hf_saddr , tvb , offset , 4 , FALSE ) ;
2001-05-20 22:20:33 +00:00
offset + = 4 ;
}
/* aux data */
if ( adl ) {
2001-07-10 20:55:54 +00:00
proto_tree_add_item ( tree , hf_aux_data , tvb , offset , adl * 4 ,
FALSE ) ;
2001-05-20 22:20:33 +00:00
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 ;
2001-06-12 06:21:55 +00:00
PRINT_IGMP_VERSION ( 3 ) ;
2001-05-20 22:20:33 +00:00
/* 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 ;
2001-06-12 06:21:55 +00:00
PRINT_IGMP_VERSION ( 3 ) ;
2001-05-20 22:20:33 +00:00
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 */
2001-07-10 20:55:54 +00:00
proto_tree_add_item ( tree , hf_maddr , tvb , offset , 4 , FALSE ) ;
2001-05-20 22:20:33 +00:00
offset + = 4 ;
/* bitmask for S and QRV */
offset = dissect_v3_sqrv_bits ( tvb , pinfo , tree , offset ) ;
/* qqic */
2001-07-10 20:55:54 +00:00
proto_tree_add_item ( tree , hf_qqic , tvb , offset , 1 , FALSE ) ;
2001-05-20 22:20:33 +00:00
offset + = 1 ;
/*number of sources*/
proto_tree_add_uint ( tree , hf_num_src , tvb , offset , 2 , num ) ;
offset + = 2 ;
while ( num - - ) {
2001-07-10 20:55:54 +00:00
proto_tree_add_item ( tree , hf_saddr , tvb , offset , 4 , FALSE ) ;
2001-05-20 22:20:33 +00:00
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 ;
2001-06-12 06:21:55 +00:00
PRINT_IGMP_VERSION ( 2 ) ;
2001-05-20 22:20:33 +00:00
/* 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 */
2001-07-10 20:55:54 +00:00
proto_tree_add_item ( tree , hf_maddr , tvb , offset , 4 , FALSE ) ;
2001-05-20 22:20:33 +00:00
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 )
{
2001-06-12 06:21:55 +00:00
PRINT_IGMP_VERSION ( 1 ) ;
2001-05-20 22:20:33 +00:00
/* skip unused byte */
offset + = 1 ;
/* checksum */
igmp_checksum ( tree , tvb , 8 ) ;
offset + = 2 ;
/* group address */
2001-07-10 20:55:54 +00:00
proto_tree_add_item ( tree , hf_maddr , tvb , offset , 4 , FALSE ) ;
2001-05-20 22:20:33 +00:00
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 ;
2001-06-12 06:21:55 +00:00
PRINT_IGMP_VERSION ( 0 ) ;
2001-05-20 22:20:33 +00:00
/* 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 */
2001-07-10 20:55:54 +00:00
proto_tree_add_item ( tree , hf_identifier , tvb , offset , 4 , FALSE ) ;
2001-05-20 22:20:33 +00:00
offset + = 4 ;
/* group address */
2001-07-10 20:55:54 +00:00
proto_tree_add_item ( tree , hf_maddr , tvb , offset , 4 , FALSE ) ;
2001-05-20 22:20:33 +00:00
offset + = 4 ;
/* access key */
2001-07-10 20:55:54 +00:00
proto_tree_add_item ( tree , hf_access_key , tvb , offset , 8 , FALSE ) ;
2001-05-20 22:20:33 +00:00
offset + = 8 ;
return offset ;
}
2001-07-10 20:55:54 +00:00
/* 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_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_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 ;
}
2001-05-20 22:20:33 +00:00
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 ;
2001-06-27 20:19:19 +00:00
guint32 dst ;
2001-05-20 22:20:33 +00:00
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 ) ;
}
2001-05-25 06:47:02 +00:00
switch ( type ) {
case IGMP_V1_HOST_MEMBERSHIP_QUERY : /* 0x11 v1/v2/v3 */
2001-05-20 22:20:33 +00:00
if ( ( pinfo - > iplen - pinfo - > iphdrlen * 4 ) > = 12 ) {
2001-05-25 06:47:02 +00:00
/* version 3 */
2001-05-20 22:20:33 +00:00
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 ) ;
}
}
2001-05-25 06:47:02 +00:00
break ;
2001-05-20 22:20:33 +00:00
2001-05-25 06:47:02 +00:00
case IGMP_V1_HOST_MEMBERSHIP_REPORT : /* 0x12 v1/v2 */
2001-05-20 22:20:33 +00:00
/* 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 ) ;
}
2001-05-25 06:47:02 +00:00
break ;
2001-06-12 06:21:55 +00:00
case IGMP_DVMRP :
offset = dissect_dvmrp ( tvb , pinfo , parent_tree , offset ) ;
2001-05-25 06:47:02 +00:00
break ;
case IGMP_V1_PIM_ROUTING_MESSAGE :
2001-07-02 09:23:02 +00:00
offset = dissect_pimv1 ( tvb , pinfo , parent_tree , offset ) ;
2001-05-25 06:47:02 +00:00
break ;
case IGMP_V2_MEMBERSHIP_REPORT :
case IGMP_V2_LEAVE_GROUP :
2001-05-20 22:20:33 +00:00
offset = dissect_igmp_v2 ( tvb , pinfo , tree , type , offset ) ;
2001-05-25 06:47:02 +00:00
break ;
2001-07-10 20:55:54 +00:00
case IGMP_TRACEROUTE_RESPONSE :
case IGMP_TRACEROUTE_QUERY_REQ :
offset = dissect_igmp_mtrace ( tvb , pinfo , tree , type , offset ) ;
2001-05-25 06:47:02 +00:00
break ;
case IGMP_V3_MEMBERSHIP_REPORT :
2001-05-20 22:20:33 +00:00
offset = dissect_igmp_v3_response ( tvb , pinfo , tree , type , offset ) ;
2001-05-25 06:47:02 +00:00
break ;
2001-07-02 09:23:02 +00:00
2001-06-29 18:55:50 +00:00
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 ;
2001-07-02 09:23:02 +00:00
2001-06-27 20:19:19 +00:00
case IGMP_TYPE_0x24 :
dst = htonl ( MC_ALL_ROUTERS ) ;
if ( ! memcmp ( pinfo - > dst . data , & dst , 4 ) ) {
offset = dissect_mrdisc ( tvb , pinfo , parent_tree , offset ) ;
2001-06-29 18:55:50 +00:00
}
dst = htonl ( MC_ALL_IGMPV3_ROUTERS ) ;
if ( ! memcmp ( pinfo - > dst . data , & dst , 4 ) ) {
offset = dissect_msnip ( tvb , pinfo , parent_tree , offset ) ;
2001-06-27 20:19:19 +00:00
}
break ;
2001-07-02 09:23:02 +00:00
2001-06-27 20:19:19 +00:00
case IGMP_TYPE_0x25 :
2001-06-29 18:55:50 +00:00
if ( ( pinfo - > iplen - pinfo - > iphdrlen * 4 ) > = 8 ) {
/* if len of igmp packet>=8 we assume it is MSNIP */
offset = dissect_msnip ( tvb , pinfo , parent_tree , offset ) ;
} else {
/* ok its not MSNIP, check if it might be MRDISC */
dst = htonl ( MC_ALL_ROUTERS ) ;
if ( ! memcmp ( pinfo - > dst . data , & dst , 4 ) ) {
offset = dissect_mrdisc ( tvb , pinfo , parent_tree , offset ) ;
}
2001-06-27 20:19:19 +00:00
}
break ;
2001-07-02 09:23:02 +00:00
2001-06-27 20:19:19 +00:00
case IGMP_TYPE_0x26 :
dst = htonl ( MC_ALL_ROUTERS ) ;
if ( ! memcmp ( pinfo - > dst . data , & dst , 4 ) ) {
offset = dissect_mrdisc ( tvb , pinfo , parent_tree , offset ) ;
}
break ;
2001-05-25 18:44:01 +00:00
default :
offset = dissect_igmp_unknown ( tvb , pinfo , tree , type , offset ) ;
break ;
2001-05-20 22:20:33 +00:00
}
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 ,
2001-06-18 02:18:27 +00:00
VALS ( commands ) , 0 , " IGMP Packet Type " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_version ,
{ " IGMP Version " , " igmp.version " , FT_UINT8 , BASE_DEC ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " IGMP Version " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_group_type ,
{ " Type Of Group " , " igmp.group_type " , FT_UINT8 , BASE_DEC ,
2001-06-18 02:18:27 +00:00
VALS ( vs_group_type ) , 0 , " IGMP V0 Type Of Group " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_reply_code ,
{ " Reply " , " igmp.reply " , FT_UINT8 , BASE_DEC ,
2001-06-18 02:18:27 +00:00
VALS ( vs_reply_code ) , 0 , " IGMP V0 Reply " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_reply_pending ,
{ " Reply Pending " , " igmp.reply.pending " , FT_UINT8 , BASE_DEC ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " IGMP V0 Reply Pending, Retry in this many seconds " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_checksum ,
{ " Checksum " , " igmp.checksum " , FT_UINT16 , BASE_HEX ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " IGMP Checksum " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_checksum_bad ,
{ " Bad Checksum " , " igmp.checksum_bad " , FT_BOOLEAN , BASE_NONE ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " Bad IGMP Checksum " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_identifier ,
{ " Identifier " , " igmp.identifier " , FT_UINT32 , BASE_DEC ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " IGMP V0 Identifier " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_access_key ,
{ " Access Key " , " igmp.access_key " , FT_BYTES , BASE_HEX ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " IGMP V0 Access Key " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_max_resp ,
{ " Max Resp Time " , " igmp.max_resp " , FT_UINT8 , BASE_DEC ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " Max Response Time " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_supress ,
{ " S " , " igmp.s " , FT_BOOLEAN , 8 ,
2001-06-18 02:18:27 +00:00
TFS ( & tfs_s ) , IGMP_V3_S , " Supress Router Side Processing " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_qrv ,
{ " QRV " , " igmp.qrv " , FT_UINT8 , BASE_DEC ,
2001-06-18 02:18:27 +00:00
NULL , IGMP_V3_QRV_MASK , " Querier's Robustness Value " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_qqic ,
{ " QQIC " , " igmp.qqic " , FT_UINT8 , BASE_DEC ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " Querier's Query Interval Code " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_num_src ,
{ " Num Src " , " igmp.num_src " , FT_UINT16 , BASE_DEC ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " Number Of Sources " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_saddr ,
{ " Source Address " , " igmp.saddr " , FT_IPv4 , BASE_NONE ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " Source Address " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_num_grp_recs ,
{ " Num Group Records " , " igmp.num_grp_recs " , FT_UINT16 , BASE_DEC ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " Number Of Group Records " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_record_type ,
{ " Record Type " , " igmp.record_type " , FT_UINT8 , BASE_DEC ,
2001-06-18 02:18:27 +00:00
VALS ( vs_record_type ) , 0 , " Record Type " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_aux_data_len ,
{ " Aux Data Len " , " igmp.aux_data_len " , FT_UINT8 , BASE_DEC ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " Aux Data Len, In units of 32bit words " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_maddr ,
{ " Multicast Address " , " igmp.maddr " , FT_IPv4 , BASE_NONE ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " Multicast Address " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_aux_data ,
{ " Aux Data " , " igmp.aux_data " , FT_BYTES , BASE_HEX ,
2001-06-18 02:18:27 +00:00
NULL , 0 , " IGMP V3 Auxiliary Data " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_max_resp_exp ,
{ " Exponent " , " igmp.max_resp.exp " , FT_UINT8 , BASE_HEX ,
2001-06-18 02:18:27 +00:00
NULL , IGMP_MAX_RESP_EXP , " Maxmimum Response Time, Exponent " , HFILL } } ,
2001-05-20 22:20:33 +00:00
{ & hf_max_resp_mant ,
{ " Mantissa " , " igmp.max_resp.mant " , FT_UINT8 , BASE_HEX ,
2001-06-18 02:18:27 +00:00
NULL , IGMP_MAX_RESP_MANT , " Maxmimum Response Time, Mantissa " , HFILL } } ,
2001-05-20 22:20:33 +00:00
2001-07-10 20:55:54 +00:00
{ & 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 } } ,
2001-05-20 22:20:33 +00:00
} ;
static gint * ett [ ] = {
& ett_igmp ,
& ett_group_record ,
& ett_sqrv_bits ,
& ett_max_resp ,
2001-07-10 20:55:54 +00:00
& ett_mtrace_block ,
2001-05-20 22:20:33 +00:00
} ;
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 ) ;
}