1 /* packet-igmp.c 2001 Ronnie Sahlberg <rsahlber@bigpond.net.au>
2 * Routines for IGMP packet disassembly
4 * $Id: packet-igmp.c,v 1.8 2001/07/02 09:23:02 guy Exp $
6 * Ethereal - Network traffic analyzer
7 * By Gerald Combs <gerald@ethereal.com>
8 * Copyright 1998 Gerald Combs
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25 IGMP is defined in the following RFCs
26 RFC988 Version 0 Obsolete
28 RFC1112 Version 1 (same as RFC1054 as far as we are concerned)
30 draft-ietf-idmr-igmp-v3-07 Version 3
32 Size in bytes for each packet
33 type RFC988 RFC1054 RFC2236 RFC???? DVMRP MRDISC MSNIP
55 * Differs in second byte of protocol. Always 0 in V1
57 x DVMRP Protocol see packet-dvmrp.c
59 DVMRP is defined in the following RFCs
61 draft-ietf-idmr-dvmrp-v3-10.txt Version 3
63 V1 and V3 can be distinguished by looking at bytes 6 and 7 in the
65 If header[6]==0xff and header[7]==0x03 we have version 3.
67 a MRDISC Protocol see packet-mrdisc.c
69 MRDISC : IGMP Multicast Router DISCovery
70 draft-ietf-idmr-igmp-mrdisc-06.txt
71 TTL == 1 and IP.DST==224.0.0.2 for all packets
73 b MSNIP Protocol see packet-msnip.c
75 MSNIP : Multicast Source Notification of Interest Protocol
76 draft-ietf-idmr-msnip-00.txt
77 0x23, 0x24 are sent with ip.dst==224.0.0.22
78 0x25 is sent as unicast.
86 #ifdef HAVE_SYS_TYPES_H
87 # include <sys/types.h>
97 #include "packet-dvmrp.h"
98 #include "packet-pim.h"
99 #include "packet-mrdisc.h"
100 #include "packet-msnip.h"
102 static int proto_igmp = -1;
103 static int hf_type = -1;
104 static int hf_version = -1;
105 static int hf_group_type = -1;
106 static int hf_reply_code = -1;
107 static int hf_reply_pending = -1;
108 static int hf_checksum = -1;
109 static int hf_checksum_bad = -1;
110 static int hf_identifier = -1;
111 static int hf_access_key = -1;
112 static int hf_max_resp = -1;
113 static int hf_max_resp_exp = -1;
114 static int hf_max_resp_mant = -1;
115 static int hf_supress = -1;
116 static int hf_qrv = -1;
117 static int hf_qqic = -1;
118 static int hf_num_src = -1;
119 static int hf_saddr = -1;
120 static int hf_num_grp_recs = -1;
121 static int hf_record_type = -1;
122 static int hf_aux_data_len = -1;
123 static int hf_maddr = -1;
124 static int hf_aux_data = -1;
126 static int ett_igmp = -1;
127 static int ett_group_record = -1;
128 static int ett_sqrv_bits = -1;
129 static int ett_max_resp = -1;
131 #define MC_ALL_ROUTERS 0xe0000002
132 #define MC_ALL_IGMPV3_ROUTERS 0xe0000016
135 #define IGMP_V0_CREATE_GROUP_REQUEST 0x01
136 #define IGMP_V0_CREATE_GROUP_REPLY 0x02
137 #define IGMP_V0_JOIN_GROUP_REQUEST 0x03
138 #define IGMP_V0_JOIN_GROUP_REPLY 0x04
139 #define IGMP_V0_LEAVE_GROUP_REQUEST 0x05
140 #define IGMP_V0_LEAVE_GROUP_REPLY 0x06
141 #define IGMP_V0_CONFIRM_GROUP_REQUEST 0x07
142 #define IGMP_V0_CONFIRM_GROUP_REPLY 0x08
143 #define IGMP_V1_HOST_MEMBERSHIP_QUERY 0x11
144 #define IGMP_V1_HOST_MEMBERSHIP_REPORT 0x12
145 #define IGMP_DVMRP 0x13
146 #define IGMP_V1_PIM_ROUTING_MESSAGE 0x14
147 #define IGMP_V2_MEMBERSHIP_REPORT 0x16
148 #define IGMP_V2_LEAVE_GROUP 0x17
149 #define IGMP_V1_TRACEROUTE_RESPONSE 0x1e /* XXX */
150 #define IGMP_V1_TRACEROUTE_MESSAGE 0x1f /* XXX */
151 #define IGMP_V3_MEMBERSHIP_REPORT 0x22
152 #define IGMP_TYPE_0x23 0x23
153 #define IGMP_TYPE_0x24 0x24
154 #define IGMP_TYPE_0x25 0x25
155 #define IGMP_TYPE_0x26 0x26
157 static const value_string commands[] = {
158 {IGMP_V0_CREATE_GROUP_REQUEST, "Create Group Request" },
159 {IGMP_V0_CREATE_GROUP_REPLY, "Create Group Reply" },
160 {IGMP_V0_JOIN_GROUP_REQUEST, "Join Group Request" },
161 {IGMP_V0_JOIN_GROUP_REPLY, "Join Group Reply" },
162 {IGMP_V0_LEAVE_GROUP_REQUEST, "Leave Group Request" },
163 {IGMP_V0_LEAVE_GROUP_REPLY, "Leave Group Reply" },
164 {IGMP_V0_CONFIRM_GROUP_REQUEST, "Confirm Group Request" },
165 {IGMP_V0_CONFIRM_GROUP_REPLY, "Confirm Group Reply" },
166 {IGMP_V1_HOST_MEMBERSHIP_QUERY, "Membership Query" },
167 {IGMP_V1_HOST_MEMBERSHIP_REPORT,"Membership Report" },
168 {IGMP_DVMRP, "DVMRP Protocol" },
169 {IGMP_V1_PIM_ROUTING_MESSAGE, "PIM Routing Message" },
170 {IGMP_V2_MEMBERSHIP_REPORT, "Membership Report" },
171 {IGMP_V2_LEAVE_GROUP, "Leave Group" },
172 {IGMP_V1_TRACEROUTE_RESPONSE, "Traceroute Response" },
173 {IGMP_V1_TRACEROUTE_MESSAGE, "Traceroute Message" },
174 {IGMP_V3_MEMBERSHIP_REPORT, "Membership Report" },
178 #define IGMP_V3_S 0x08
179 #define IGMP_V3_QRV_MASK 0x07
181 #define IGMP_MAX_RESP_EXP 0x70
182 #define IGMP_MAX_RESP_MANT 0x0f
184 #define IGMP_V0_GROUP_PUBLIC 0x00
185 #define IGMP_V0_GROUP_PRIVATE 0x01
187 static const value_string vs_group_type[] = {
188 {IGMP_V0_GROUP_PUBLIC, "Public Group" },
189 {IGMP_V0_GROUP_PRIVATE, "Private Group" },
193 #define IGMP_V0_REPLY_GRANTED 0x00
194 #define IGMP_V0_REPLY_NO_RESOURCES 0x01
195 #define IGMP_V0_REPLY_INVALID_CODE 0x02
196 #define IGMP_V0_REPLY_INVALID_GROUP 0x03
197 #define IGMP_V0_REPLY_INVALID_KEY 0x04
199 static const value_string vs_reply_code[] = {
200 {IGMP_V0_REPLY_GRANTED, "Request Granted" },
201 {IGMP_V0_REPLY_NO_RESOURCES, "Request Denied, No Resources" },
202 {IGMP_V0_REPLY_INVALID_CODE, "Request Denied, Invalid Code" },
203 {IGMP_V0_REPLY_INVALID_GROUP, "Request Denied, Invalid Group" },
204 {IGMP_V0_REPLY_INVALID_KEY, "Request Denied, Invalid Key" },
208 static const true_false_string tfs_s = {
209 "SUPRESS router side processing",
210 "Do not supress router side processing"
213 #define IGMP_V3_MODE_IS_INCLUDE 1
214 #define IGMP_V3_MODE_IS_EXCLUDE 2
215 #define IGMP_V3_CHANGE_TO_INCLUDE_MODE 3
216 #define IGMP_V3_CHANGE_TO_EXCLUDE_MODE 4
217 #define IGMP_V3_ALLOW_NEW_SOURCES 5
218 #define IGMP_V3_BLOCK_OLD_SOURCES 6
220 static const value_string vs_record_type[] = {
221 {IGMP_V3_MODE_IS_INCLUDE, "Mode Is Include" },
222 {IGMP_V3_MODE_IS_EXCLUDE, "Mode Is Exclude" },
223 {IGMP_V3_CHANGE_TO_INCLUDE_MODE,"Change To Include Mode" },
224 {IGMP_V3_CHANGE_TO_EXCLUDE_MODE,"Change To Exclude Mode" },
225 {IGMP_V3_ALLOW_NEW_SOURCES, "Allow New Sources" },
226 {IGMP_V3_BLOCK_OLD_SOURCES, "Block Old Sources" },
230 #define PRINT_IGMP_VERSION(version) \
231 if (check_col(pinfo->fd, COL_INFO)) { \
232 col_add_fstr(pinfo->fd, COL_INFO, \
233 "V%d %s",version,val_to_str(type, commands, \
234 "Unknown Type:0x%02x")); \
236 /* version of IGMP protocol */ \
237 proto_tree_add_uint(tree, hf_version, tvb, 0, 0, version); \
238 /* type of command */ \
239 proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type); \
242 static void igmp_checksum(proto_tree *tree,tvbuff_t *tvb, int len)
244 guint16 cksum,hdrcksum;
247 cksum_vec[0].ptr = tvb_get_ptr(tvb, 0, len);
248 cksum_vec[0].len = len;
250 hdrcksum = tvb_get_ntohs(tvb, 2);
251 cksum = in_cksum(&cksum_vec[0],1);
254 proto_tree_add_uint_format(tree, hf_checksum, tvb, 2, 2, hdrcksum, "Header checksum: 0x%04x (correct)", hdrcksum);
256 proto_tree_add_item_hidden(tree, hf_checksum_bad, tvb, 2, 2, TRUE);
257 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));
264 /* Unknown IGMP message type */
266 dissect_igmp_unknown(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
270 if (check_col(pinfo->fd, COL_INFO)) {
271 col_add_str(pinfo->fd, COL_INFO,
272 val_to_str(type, commands, "Unknown Type:0x%02x"));
275 /* type of command */
276 proto_tree_add_uint(tree, hf_type, tvb, offset, 1, type);
279 /* Just call the rest of it "data" */
280 len = tvb_length_remaining(tvb, offset);
281 proto_tree_add_text(tree, tvb, offset, len, "Data");
289 /*************************************************************
290 * IGMP Protocol dissectors
291 *************************************************************/
293 dissect_v3_max_resp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
300 bits = tvb_get_guint8(tvb, offset);
302 tsecs = ((bits&IGMP_MAX_RESP_MANT)|0x10);
303 tsecs = tsecs << ( ((bits&IGMP_MAX_RESP_EXP)>>4) + 3);
308 item = proto_tree_add_uint_format(parent_tree, hf_max_resp, tvb,
309 offset, 1, tsecs, "Max Response Time: %.1f sec (0x%02x)",tsecs*0.1,bits);
312 tree = proto_item_add_subtree(item, ett_max_resp);
314 proto_tree_add_uint(tree, hf_max_resp_exp, tvb, offset, 1,
316 proto_tree_add_uint(tree, hf_max_resp_mant, tvb, offset, 1,
326 dissect_v3_sqrv_bits(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
332 bits = tvb_get_guint8(tvb, offset);
334 item = proto_tree_add_text(parent_tree, tvb, offset, 1,
335 "QRV=%d S=%s", bits&IGMP_V3_QRV_MASK,
336 (bits&IGMP_V3_S)?tfs_s.true_string:tfs_s.false_string);
337 tree = proto_item_add_subtree(item, ett_sqrv_bits);
340 proto_tree_add_boolean(tree, hf_supress, tvb, offset, 1, bits);
342 proto_tree_add_uint(tree, hf_qrv, tvb, offset, 1, bits);
349 dissect_v3_group_record(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, int offset)
353 int old_offset = offset;
358 ip = tvb_get_letohl(tvb, offset+4);
359 item = proto_tree_add_text(parent_tree, tvb, offset, 0,
360 "Group Record : %s %s",
361 ip_to_str((gchar*)&ip),
362 val_to_str(tvb_get_guint8(tvb, offset), vs_record_type,"")
364 tree = proto_item_add_subtree(item, ett_group_record);
367 proto_tree_add_uint(tree, hf_record_type, tvb, offset, 1, tvb_get_guint8(tvb, offset));
371 adl = tvb_get_guint8(tvb, offset);
372 proto_tree_add_uint(tree, hf_aux_data_len, tvb, offset, 1, adl);
375 /*number of sources*/
376 num = tvb_get_ntohs(tvb, offset);
377 proto_tree_add_uint(tree, hf_num_src, tvb, offset, 2, num);
380 /* multicast address */
381 proto_tree_add_ipv4(tree, hf_maddr, tvb,
382 offset, 4, tvb_get_letohl(tvb, offset));
385 /* source addresses */
387 proto_tree_add_ipv4(tree, hf_saddr, tvb,
388 offset, 4, tvb_get_letohl(tvb, offset));
394 proto_tree_add_bytes(tree, hf_aux_data, tvb, offset, adl*4, tvb_get_ptr(tvb, offset, adl*4));
398 proto_item_set_len(item, offset-old_offset);
402 /* dissectors for version 3, rfc???? */
404 dissect_igmp_v3_response(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
408 PRINT_IGMP_VERSION(3);
410 /* skip reserved field*/
414 igmp_checksum(tree, tvb, pinfo->iplen-pinfo->iphdrlen*4);
417 /* skip reserved field */
420 /* number of group records */
421 num = tvb_get_ntohs(tvb, offset);
422 proto_tree_add_uint(tree, hf_num_grp_recs, tvb, offset, 2, num);
426 offset = dissect_v3_group_record(tvb,pinfo,tree,offset);
433 dissect_igmp_v3_query(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
437 PRINT_IGMP_VERSION(3);
439 num = tvb_get_ntohs(tvb, offset+9);
441 offset = dissect_v3_max_resp(tvb, pinfo, tree, offset);
444 igmp_checksum(tree, tvb, pinfo->iplen-pinfo->iphdrlen*4);
448 proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, tvb_get_letohl(tvb, offset));
451 /* bitmask for S and QRV */
452 offset = dissect_v3_sqrv_bits(tvb, pinfo, tree, offset);
455 proto_tree_add_uint(tree, hf_qqic, tvb, offset, 1, tvb_get_guint8(tvb, offset));
458 /*number of sources*/
459 proto_tree_add_uint(tree, hf_num_src, tvb, offset, 2, num);
463 proto_tree_add_ipv4(tree, hf_saddr, tvb,
464 offset, 4, tvb_get_letohl(tvb, offset));
471 /* dissector for version 2, rfc2236 */
473 dissect_igmp_v2(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
477 PRINT_IGMP_VERSION(2);
480 tsecs = tvb_get_guint8(tvb, offset);
481 proto_tree_add_uint_format(tree, hf_max_resp, tvb,
482 offset, 1, tsecs, "Max Response Time: %.1f sec (0x%02x)", tsecs*0.1,tsecs);
486 igmp_checksum(tree, tvb, 8);
490 proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, tvb_get_letohl(tvb, offset));
496 /* dissector for version 1, rfc1054 */
498 dissect_igmp_v1(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
500 PRINT_IGMP_VERSION(1);
502 /* skip unused byte */
506 igmp_checksum(tree, tvb, 8);
510 proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, tvb_get_letohl(tvb, offset));
516 /* dissector for version 0, rfc988 */
518 dissect_igmp_v0(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, int type, int offset)
522 PRINT_IGMP_VERSION(0);
525 code = tvb_get_guint8(tvb, offset);
526 if (type==IGMP_V0_CREATE_GROUP_REQUEST) {
527 proto_tree_add_uint(tree, hf_group_type, tvb, offset, 1, code);
528 } else if (!(type&0x01)) {
530 proto_tree_add_uint(tree, hf_reply_code, tvb, offset, 1, code);
532 proto_tree_add_uint(tree, hf_reply_pending, tvb, offset, 1, code);
538 igmp_checksum(tree, tvb, 20);
542 proto_tree_add_uint(tree, hf_identifier, tvb, offset, 4, tvb_get_ntohl(tvb, offset));
546 proto_tree_add_ipv4(tree, hf_maddr, tvb, offset, 4, tvb_get_letohl(tvb, offset));
550 proto_tree_add_bytes(tree, hf_access_key, tvb, offset, 8, tvb_get_ptr(tvb, offset, 8));
557 dissect_igmp(tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree)
565 item = proto_tree_add_item(parent_tree, proto_igmp, tvb, offset, 0, FALSE);
566 tree = proto_item_add_subtree(item, ett_igmp);
569 if (check_col(pinfo->fd, COL_PROTOCOL)) {
570 col_set_str(pinfo->fd, COL_PROTOCOL, "IGMP");
572 if (check_col(pinfo->fd, COL_INFO)) {
573 col_clear(pinfo->fd, COL_INFO);
577 type = tvb_get_guint8(tvb, offset);
582 offset = dissect_igmp_v0(tvb, pinfo, tree, type, offset);
588 case IGMP_V1_HOST_MEMBERSHIP_QUERY: /* 0x11 v1/v2/v3 */
589 if ( (pinfo->iplen-pinfo->iphdrlen*4)>=12 ) {
591 offset = dissect_igmp_v3_query(tvb, pinfo, tree, type, offset);
593 /* v1 and v2 differs in second byte of header */
594 if (tvb_get_guint8(tvb, offset)) {
595 offset = dissect_igmp_v2(tvb, pinfo, tree, type, offset);
597 offset = dissect_igmp_v1(tvb, pinfo, tree, type, offset);
602 case IGMP_V1_HOST_MEMBERSHIP_REPORT: /* 0x12 v1/v2 */
603 /* v1 and v2 differs in second byte of header */
604 if (tvb_get_guint8(tvb, offset)) {
605 offset = dissect_igmp_v2(tvb, pinfo, tree, type, offset);
607 offset = dissect_igmp_v1(tvb, pinfo, tree, type, offset);
612 offset = dissect_dvmrp(tvb, pinfo, parent_tree, offset);
615 case IGMP_V1_PIM_ROUTING_MESSAGE:
616 offset = dissect_pimv1(tvb, pinfo, parent_tree, offset);
619 case IGMP_V2_MEMBERSHIP_REPORT:
620 case IGMP_V2_LEAVE_GROUP:
621 offset = dissect_igmp_v2(tvb, pinfo, tree, type, offset);
624 case IGMP_V1_TRACEROUTE_RESPONSE:
625 /* XXX - V1 or V2? */
626 offset = dissect_igmp_v1(tvb, pinfo, tree, type, offset);
628 * XXX - dissect the rest as traceroute response; see the
629 * tcpdump IGMP dissector.
633 case IGMP_V1_TRACEROUTE_MESSAGE:
634 /* XXX - V1 or V2? */
635 offset = dissect_igmp_v1(tvb, pinfo, tree, type, offset);
637 * XXX - dissect the rest as traceroute message; see the
638 * tcpdump IGMP dissector.
642 case IGMP_V3_MEMBERSHIP_REPORT:
643 offset = dissect_igmp_v3_response(tvb, pinfo, tree, type, offset);
647 dst = htonl(MC_ALL_IGMPV3_ROUTERS);
648 if (!memcmp(pinfo->dst.data, &dst, 4)) {
649 offset = dissect_msnip(tvb, pinfo, parent_tree, offset);
654 dst = htonl(MC_ALL_ROUTERS);
655 if (!memcmp(pinfo->dst.data, &dst, 4)) {
656 offset = dissect_mrdisc(tvb, pinfo, parent_tree, offset);
658 dst = htonl(MC_ALL_IGMPV3_ROUTERS);
659 if (!memcmp(pinfo->dst.data, &dst, 4)) {
660 offset = dissect_msnip(tvb, pinfo, parent_tree, offset);
665 if ( (pinfo->iplen-pinfo->iphdrlen*4)>=8 ) {
666 /* if len of igmp packet>=8 we assume it is MSNIP */
667 offset = dissect_msnip(tvb, pinfo, parent_tree, offset);
669 /* ok its not MSNIP, check if it might be MRDISC */
670 dst = htonl(MC_ALL_ROUTERS);
671 if (!memcmp(pinfo->dst.data, &dst, 4)) {
672 offset = dissect_mrdisc(tvb, pinfo, parent_tree, offset);
678 dst = htonl(MC_ALL_ROUTERS);
679 if (!memcmp(pinfo->dst.data, &dst, 4)) {
680 offset = dissect_mrdisc(tvb, pinfo, parent_tree, offset);
685 offset = dissect_igmp_unknown(tvb, pinfo, tree, type, offset);
690 proto_item_set_len(item, offset);
694 proto_register_igmp(void)
696 static hf_register_info hf[] = {
698 { "Type", "igmp.type", FT_UINT8, BASE_HEX,
699 VALS(commands), 0, "IGMP Packet Type", HFILL }},
702 { "IGMP Version", "igmp.version", FT_UINT8, BASE_DEC,
703 NULL, 0, "IGMP Version", HFILL }},
706 { "Type Of Group", "igmp.group_type", FT_UINT8, BASE_DEC,
707 VALS(vs_group_type), 0, "IGMP V0 Type Of Group", HFILL }},
710 { "Reply", "igmp.reply", FT_UINT8, BASE_DEC,
711 VALS(vs_reply_code), 0, "IGMP V0 Reply", HFILL }},
714 { "Reply Pending", "igmp.reply.pending", FT_UINT8, BASE_DEC,
715 NULL, 0, "IGMP V0 Reply Pending, Retry in this many seconds", HFILL }},
718 { "Checksum", "igmp.checksum", FT_UINT16, BASE_HEX,
719 NULL, 0, "IGMP Checksum", HFILL }},
722 { "Bad Checksum", "igmp.checksum_bad", FT_BOOLEAN, BASE_NONE,
723 NULL, 0, "Bad IGMP Checksum", HFILL }},
726 { "Identifier", "igmp.identifier", FT_UINT32, BASE_DEC,
727 NULL, 0, "IGMP V0 Identifier", HFILL }},
730 { "Access Key", "igmp.access_key", FT_BYTES, BASE_HEX,
731 NULL, 0, "IGMP V0 Access Key", HFILL }},
734 { "Max Resp Time", "igmp.max_resp", FT_UINT8, BASE_DEC,
735 NULL, 0, "Max Response Time", HFILL }},
738 { "S", "igmp.s", FT_BOOLEAN, 8,
739 TFS(&tfs_s), IGMP_V3_S, "Supress Router Side Processing", HFILL }},
742 { "QRV", "igmp.qrv", FT_UINT8, BASE_DEC,
743 NULL, IGMP_V3_QRV_MASK, "Querier's Robustness Value", HFILL }},
746 { "QQIC", "igmp.qqic", FT_UINT8, BASE_DEC,
747 NULL, 0, "Querier's Query Interval Code", HFILL }},
750 { "Num Src", "igmp.num_src", FT_UINT16, BASE_DEC,
751 NULL, 0, "Number Of Sources", HFILL }},
754 { "Source Address", "igmp.saddr", FT_IPv4, BASE_NONE,
755 NULL, 0, "Source Address", HFILL }},
758 { "Num Group Records", "igmp.num_grp_recs", FT_UINT16, BASE_DEC,
759 NULL, 0, "Number Of Group Records", HFILL }},
762 { "Record Type", "igmp.record_type", FT_UINT8, BASE_DEC,
763 VALS(vs_record_type), 0, "Record Type", HFILL }},
766 { "Aux Data Len", "igmp.aux_data_len", FT_UINT8, BASE_DEC,
767 NULL, 0, "Aux Data Len, In units of 32bit words", HFILL }},
770 { "Multicast Address", "igmp.maddr", FT_IPv4, BASE_NONE,
771 NULL, 0, "Multicast Address", HFILL }},
774 { "Aux Data", "igmp.aux_data", FT_BYTES, BASE_HEX,
775 NULL, 0, "IGMP V3 Auxiliary Data", HFILL }},
778 { "Exponent", "igmp.max_resp.exp", FT_UINT8, BASE_HEX,
779 NULL, IGMP_MAX_RESP_EXP, "Maxmimum Response Time, Exponent", HFILL }},
782 { "Mantissa", "igmp.max_resp.mant", FT_UINT8, BASE_HEX,
783 NULL, IGMP_MAX_RESP_MANT, "Maxmimum Response Time, Mantissa", HFILL }},
786 static gint *ett[] = {
793 proto_igmp = proto_register_protocol("Internet Group Management Protocol",
795 proto_register_field_array(proto_igmp, hf, array_length(hf));
796 proto_register_subtree_array(ett, array_length(ett));
800 proto_reg_handoff_igmp(void)
802 dissector_add("ip.proto", IP_PROTO_IGMP, dissect_igmp, proto_igmp);