]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-igmp.c
This commit was generated by cvs2svn to compensate for changes in r124361,
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-igmp.c
1 /*
2  * Copyright (c) 1988, 1989, 1990, 1991, 1993, 1994, 1995, 1996
3  *  The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that: (1) source code distributions
7  * retain the above copyright notice and this paragraph in its entirety, (2)
8  * distributions including binary code include the above copyright notice and
9  * this paragraph in its entirety in the documentation or other materials
10  * provided with the distribution, and (3) all advertising materials mentioning
11  * features or use of this software display the following acknowledgement:
12  * ``This product includes software developed by the University of California,
13  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
14  * the University nor the names of its contributors may be used to endorse
15  * or promote products derived from this software without specific prior
16  * written permission.
17  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
18  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
19  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
20  */
21
22 #ifndef lint
23 static const char rcsid[] =
24     "@(#) $Header: /tcpdump/master/tcpdump/print-igmp.c,v 1.5.4.1 2002/06/02 18:25:05 guy Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <sys/param.h>
32 #include <sys/socket.h>
33
34 #include <netinet/in.h>
35
36 #include <stdio.h>
37 #include <string.h>
38
39 #include "interface.h"
40 #include "addrtoname.h"
41 #include "extract.h"            /* must come after interface.h */
42
43 #ifndef IN_CLASSD
44 #define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000)
45 #endif
46
47 /* (following from ipmulti/mrouted/prune.h) */
48
49 /*
50  * The packet format for a traceroute request.
51  */
52 struct tr_query {
53     u_int  tr_src;          /* traceroute source */
54     u_int  tr_dst;          /* traceroute destination */
55     u_int  tr_raddr;        /* traceroute response address */
56     u_int  tr_rttlqid;      /* response ttl and qid */
57 };
58
59 #define TR_GETTTL(x)        (int)(((x) >> 24) & 0xff)
60 #define TR_GETQID(x)        ((x) & 0x00ffffff)
61
62 /*
63  * Traceroute response format.  A traceroute response has a tr_query at the
64  * beginning, followed by one tr_resp for each hop taken.
65  */
66 struct tr_resp {
67     u_int tr_qarr;          /* query arrival time */
68     u_int tr_inaddr;        /* incoming interface address */
69     u_int tr_outaddr;       /* outgoing interface address */
70     u_int tr_rmtaddr;       /* parent address in source tree */
71     u_int tr_vifin;         /* input packet count on interface */
72     u_int tr_vifout;        /* output packet count on interface */
73     u_int tr_pktcnt;        /* total incoming packets for src-grp */
74     u_char  tr_rproto;      /* routing proto deployed on router */
75     u_char  tr_fttl;        /* ttl required to forward on outvif */
76     u_char  tr_smask;       /* subnet mask for src addr */
77     u_char  tr_rflags;      /* forwarding error codes */
78 };
79
80 /* defs within mtrace */
81 #define TR_QUERY 1
82 #define TR_RESP 2
83
84 /* fields for tr_rflags (forwarding error codes) */
85 #define TR_NO_ERR   0
86 #define TR_WRONG_IF 1
87 #define TR_PRUNED   2
88 #define TR_OPRUNED  3
89 #define TR_SCOPED   4
90 #define TR_NO_RTE   5
91 #define TR_NO_FWD   7
92 #define TR_NO_SPACE 0x81
93 #define TR_OLD_ROUTER   0x82
94
95 /* fields for tr_rproto (routing protocol) */
96 #define TR_PROTO_DVMRP  1
97 #define TR_PROTO_MOSPF  2
98 #define TR_PROTO_PIM    3
99 #define TR_PROTO_CBT    4
100
101 /* igmpv3 report types */
102 static struct tok igmpv3report2str[] = {
103         { 1,    "is_in" },
104         { 2,    "is_ex" },
105         { 3,    "to_in" },
106         { 4,    "to_ex" },
107         { 5,    "allow" },
108         { 6,    "block" },
109         { 0,    NULL }
110 };
111
112 static void 
113 print_mtrace(register const u_char *bp, register u_int len)
114 {
115     register const struct tr_query *tr = (const struct tr_query *)(bp + 8);
116
117     printf("mtrace %lu: %s to %s reply-to %s",
118         (u_long)TR_GETQID(ntohl(tr->tr_rttlqid)),
119         ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
120         ipaddr_string(&tr->tr_raddr));
121     if (IN_CLASSD(ntohl(tr->tr_raddr)))
122         printf(" with-ttl %d", TR_GETTTL(ntohl(tr->tr_rttlqid)));
123 }
124
125 static void 
126 print_mresp(register const u_char *bp, register u_int len)
127 {
128     register const struct tr_query *tr = (const struct tr_query *)(bp + 8);
129
130     printf("mresp %lu: %s to %s reply-to %s",
131         (u_long)TR_GETQID(ntohl(tr->tr_rttlqid)),
132         ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
133         ipaddr_string(&tr->tr_raddr));
134     if (IN_CLASSD(ntohl(tr->tr_raddr)))
135         printf(" with-ttl %d", TR_GETTTL(ntohl(tr->tr_rttlqid)));
136 }
137
138 static void 
139 print_igmpv3_report(register const u_char *bp, register u_int len)
140 {
141     u_int group, nsrcs, ngroups;
142     register u_int i, j;
143
144     /* Minimum len is 16, and should be a multiple of 4 */
145     if (len < 16 || len & 0x03) {
146         (void)printf(" [invalid len %d]", len);
147         return;
148     }
149     TCHECK2(bp[6], 2);
150     ngroups = EXTRACT_16BITS(&bp[6]);
151     (void)printf(", %d group record(s)", ngroups); 
152     if (vflag > 0) {
153         /* Print the group records */
154         group = 8;
155         for (i=0; i<ngroups; i++) {
156             if (len < group+8) {
157                 (void)printf(" [invalid number of groups]");
158                 return;
159             }
160             TCHECK2(bp[group+4], 4);
161             (void)printf(" [gaddr %s", ipaddr_string(&bp[group+4]));
162             (void)printf(" %s", tok2str(igmpv3report2str, " [v3-report-#%d]",
163                                                                 bp[group]));
164             nsrcs = EXTRACT_16BITS(&bp[group+2]);
165             /* Check the number of sources and print them */
166             if (len < group+8+(nsrcs<<2)) {
167                 (void)printf(" [invalid number of sources %d]", nsrcs);
168                 return;
169             }
170             if (vflag == 1)
171                 (void)printf(", %d source(s)", nsrcs);
172             else {
173                 /* Print the sources */
174                 (void)printf(" {");
175                 for (j=0; j<nsrcs; j++) {
176                     TCHECK2(bp[group+8+(j<<2)], 4);
177                     (void)printf(" %s", ipaddr_string(&bp[group+8+(j<<2)]));
178                 }
179                 (void)printf(" }");
180             }
181             /* Next group record */
182             group += 8 + (nsrcs << 2);
183             (void)printf("]");
184         }
185     }
186     return;
187 trunc:
188     (void)printf("[|igmp]");
189     return;
190 }
191
192 static void
193 print_igmpv3_query(register const u_char *bp, register u_int len)
194 {
195     u_int mrc;
196     int mrt;
197     u_int nsrcs;
198     register u_int i;
199
200     (void)printf(" v3");
201     /* Minimum len is 12, and should be a multiple of 4 */
202     if (len < 12 || len & 0x03) {
203         (void)printf(" [invalid len %d]", len);
204         return;
205     }
206     mrc = bp[1];
207     if (mrc < 128) {
208         mrt = mrc;
209     } else {
210         mrt = ((mrc & 0x0f) | 0x10) << (((mrc & 0x70) >> 4) + 3);
211     }
212     if (mrc != 100) {
213         (void)printf(" [max resp time ");
214         relts_print(mrt);
215         (void)printf("]");
216     }
217     TCHECK2(bp[4], 4);
218     if (EXTRACT_32BITS(&bp[4]) == 0)
219         return;
220     (void)printf(" [gaddr %s", ipaddr_string(&bp[4]));
221     TCHECK2(bp[10], 2);
222     nsrcs = EXTRACT_16BITS(&bp[10]);
223     if (nsrcs > 0) {
224         if (len < 12 + (nsrcs << 2))
225             (void)printf(" [invalid number of sources]");
226         else if (vflag > 1) {
227             (void)printf(" {");
228             for (i=0; i<nsrcs; i++) {
229                 TCHECK2(bp[12+(i<<2)], 4);
230                 (void)printf(" %s", ipaddr_string(&bp[12+(i<<2)]));
231             }
232             (void)printf(" }");
233         } else
234             (void)printf(", %d source(s)", nsrcs);
235     }
236     (void)printf("]");
237     return;
238 trunc:
239     (void)printf("[|igmp]");
240     return;
241 }
242
243 void
244 igmp_print(register const u_char *bp, register u_int len)
245 {
246     if (qflag) {
247         (void)printf("igmp");
248         return;
249     }
250
251     TCHECK2(bp[0], 8);
252     switch (bp[0]) {
253     case 0x11:
254         (void)printf("igmp query");
255         if (len >= 12)
256             print_igmpv3_query(bp, len);
257         else {
258             if (bp[1]) {
259                 (void)printf(" v2");
260                 if (bp[1] != 100)
261                     (void)printf(" [max resp time %d]", bp[1]);
262             } else
263                 (void)printf(" v1");
264             if (EXTRACT_32BITS(&bp[4]))
265                 (void)printf(" [gaddr %s]", ipaddr_string(&bp[4]));
266             if (len != 8)
267                 (void)printf(" [len %d]", len);
268         }
269         break;
270     case 0x12:
271         (void)printf("igmp v1 report %s", ipaddr_string(&bp[4]));
272         if (len != 8)
273             (void)printf(" [len %d]", len);
274         break;
275     case 0x16:
276         (void)printf("igmp v2 report %s", ipaddr_string(&bp[4]));
277         break;
278     case 0x22:
279         (void)printf("igmp v3 report");
280         print_igmpv3_report(bp, len);
281         break;
282     case 0x17:
283         (void)printf("igmp leave %s", ipaddr_string(&bp[4]));
284         break;
285     case 0x13:
286         (void)printf("igmp dvmrp");
287         if (len < 8)
288             (void)printf(" [len %d]", len);
289         else
290             dvmrp_print(bp, len);
291         break;
292     case 0x14:
293         (void)printf("igmp pimv1");
294         pimv1_print(bp, len);
295         break;
296     case 0x1e:
297         print_mresp(bp, len);
298         break;
299     case 0x1f:
300         print_mtrace(bp, len);
301         break;
302     default:
303         (void)printf("igmp-%d", bp[0]);
304         break;
305     }
306
307     if (vflag && TTEST2(bp[0], len)) {
308         /* Check the IGMP checksum */
309         if (in_cksum((const u_short*)bp, len, 0))
310             printf(" bad igmp cksum %x!", EXTRACT_16BITS(&bp[2]));
311     }
312     return;
313 trunc:
314     fputs("[|igmp]", stdout);
315 }