4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
31 #include <sys/types.h>
32 #include <sys/socket.h>
34 #include <sys/stropts.h>
35 #include <sys/sysmacros.h>
36 #include <netinet/in_systm.h>
37 #include <netinet/in.h>
38 #include <netinet/ip.h>
39 #include <netinet/igmp.h>
41 #include <arpa/inet.h>
45 static void interpret_igmpv3qry(struct igmp
*, int);
46 static void interpret_igmpv3rpt(struct igmp
*, int);
51 interpret_igmp(int flags
, char *data
, int iplen
, int ilen
)
55 struct igmp
*igmp
= (struct igmp
*)data
;
56 char addrstr
[INET_ADDRSTRLEN
];
58 if (ilen
< IGMP_MINLEN
) {
59 /* incomplete header */
60 line
= get_sum_line();
61 (void) snprintf(line
, MAXLINE
, "Malformed IGMP packet");
65 switch (igmp
->igmp_type
) {
66 case IGMP_MEMBERSHIP_QUERY
:
67 if (ilen
== IGMP_MINLEN
) {
68 if (igmp
->igmp_code
== 0)
69 pt
= "v1 membership query";
71 pt
= "v2 membership query";
72 } else if (ilen
>= IGMP_V3_QUERY_MINLEN
) {
73 pt
= "v3 membership query";
75 pt
= "Unknown membership query";
78 case IGMP_V1_MEMBERSHIP_REPORT
:
79 pt
= "v1 membership report";
81 case IGMP_V2_MEMBERSHIP_REPORT
:
82 pt
= "v2 membership report";
84 case IGMP_V3_MEMBERSHIP_REPORT
:
85 pt
= "v3 membership report";
87 case IGMP_V2_LEAVE_GROUP
:
88 pt
= "v2 leave group";
97 line
= get_sum_line();
98 (void) snprintf(line
, MAXLINE
, "IGMP %s", pt
);
101 if (flags
& F_DTAIL
) {
102 show_header("IGMP: ", "IGMP Header", ilen
);
104 (void) snprintf(get_line(0, 0), get_line_remain(),
105 "Type = %d (%s)", igmp
->igmp_type
, pt
);
106 (void) snprintf(get_line(0, 0), get_line_remain(),
107 "Max Response Time = %d", igmp
->igmp_code
);
108 (void) snprintf(get_line(0, 0), get_line_remain(),
109 "Checksum = %x", ntohs(igmp
->igmp_cksum
));
111 if (igmp
->igmp_type
== IGMP_MEMBERSHIP_QUERY
&&
112 ilen
>= IGMP_V3_QUERY_MINLEN
) {
113 interpret_igmpv3qry(igmp
, ilen
);
114 } else if (igmp
->igmp_type
== IGMP_V3_MEMBERSHIP_REPORT
) {
115 interpret_igmpv3rpt(igmp
, ilen
);
117 (void) snprintf(get_line(0, 0), get_line_remain(),
119 inet_ntop(AF_INET
, &igmp
->igmp_group
.s_addr
,
120 addrstr
, INET_ADDRSTRLEN
));
128 interpret_igmpv3qry(struct igmp
*igmp
, int ilen
)
134 char addrstr
[INET_ADDRSTRLEN
];
136 if (ilen
< sizeof (*qry
)) {
137 (void) snprintf(get_line(0, 0), get_line_remain(),
138 "Malformed IGMP Query");
142 qry
= (struct igmp3q
*)igmp
;
143 rem
-= sizeof (*qry
);
144 srccnt
= ntohs(qry
->igmp3q_numsrc
);
145 (void) snprintf(get_line(0, 0), get_line_remain(),
146 "Group = %s", inet_ntop(AF_INET
, &qry
->igmp3q_group
, addrstr
,
148 (void) snprintf(get_line(0, 0), get_line_remain(),
149 "%d Source Address%s:", srccnt
, (srccnt
== 1) ? "" : "es");
151 src
= (struct in_addr
*)&qry
[1];
152 while (srccnt
> 0 && rem
>= sizeof (*src
)) {
153 rem
-= sizeof (*src
);
155 (void) snprintf(get_line(0, 0), get_line_remain(), " %s",
156 inet_ntop(AF_INET
, &src
->s_addr
, addrstr
, INET_ADDRSTRLEN
));
163 #define MAX_IGMPV3_REPORT_TYPE 6
165 const char *igmpv3rpt_types
[] = {
176 interpret_igmpv3rpt(struct igmp
*igmp
, int ilen
)
181 int rem
= ilen
, auxlen
;
182 uint16_t grhcnt
, srccnt
;
183 char addrstr
[INET_ADDRSTRLEN
];
185 if (ilen
< sizeof (*rpt
)) {
186 (void) snprintf(get_line(0, 0), get_line_remain(),
187 "Malformed IGMPv3 Report");
191 rpt
= (struct igmp3r
*)igmp
;
192 grh
= (struct grphdr
*)&rpt
[1];
193 grhcnt
= ntohs(rpt
->igmp3r_numrec
);
194 (void) snprintf(get_line(0, 0), get_line_remain(),
195 "%d Group Record%s:", grhcnt
, (grhcnt
== 1) ? "" : "s");
196 rem
-= sizeof (*rpt
);
197 while (grhcnt
> 0 && rem
>= sizeof (*grh
)) {
198 rem
-= sizeof (*grh
);
200 (void) snprintf(get_line(0, 0), get_line_remain(),
201 "Group = %s type = %s", inet_ntop(AF_INET
,
202 &grh
->grphdr_group
.s_addr
, addrstr
, INET_ADDRSTRLEN
),
203 (grh
->grphdr_type
> MAX_IGMPV3_REPORT_TYPE
) ?
204 "<unknown>" : igmpv3rpt_types
[grh
->grphdr_type
]);
205 srccnt
= ntohs(grh
->grphdr_numsrc
);
206 (void) snprintf(get_line(0, 0), get_line_remain(),
207 "%d Source Address%s:", srccnt
, (srccnt
== 1) ? "" : "es");
209 src
= (struct in_addr
*)&grh
[1];
210 while (srccnt
> 0 && rem
>= sizeof (*src
)) {
211 rem
-= sizeof (*src
);
213 (void) snprintf(get_line(0, 0), get_line_remain(),
214 " %s", inet_ntop(AF_INET
, &src
->s_addr
, addrstr
,
222 auxlen
= grh
->grphdr_auxlen
* 4;
224 grh
= (struct grphdr
*)((uint8_t *)src
+ auxlen
);