OSDN Git Service

Fix no pic
[uclinux-h8/uClinux-dist.git] / user / 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[] _U_ =
24     "@(#) $Header: /tcpdump/master/tcpdump/print-igmp.c,v 1.15 2004/03/24 00:59:16 guy Exp $ (LBL)";
25 #endif
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #if !defined(EMBED)
32
33 #include <tcpdump-stdinc.h>
34
35 #include <stdio.h>
36 #include <string.h>
37
38 #include "interface.h"
39 #include "addrtoname.h"
40 #include "extract.h"            /* must come after interface.h */
41
42 #ifndef IN_CLASSD
43 #define IN_CLASSD(i) (((int32_t)(i) & 0xf0000000) == 0xe0000000)
44 #endif
45
46 /* (following from ipmulti/mrouted/prune.h) */
47
48 /*
49  * The packet format for a traceroute request.
50  */
51 struct tr_query {
52     u_int32_t  tr_src;          /* traceroute source */
53     u_int32_t  tr_dst;          /* traceroute destination */
54     u_int32_t  tr_raddr;        /* traceroute response address */
55     u_int32_t  tr_rttlqid;      /* response ttl and qid */
56 };
57
58 #define TR_GETTTL(x)        (int)(((x) >> 24) & 0xff)
59 #define TR_GETQID(x)        ((x) & 0x00ffffff)
60
61 /*
62  * Traceroute response format.  A traceroute response has a tr_query at the
63  * beginning, followed by one tr_resp for each hop taken.
64  */
65 struct tr_resp {
66     u_int32_t tr_qarr;          /* query arrival time */
67     u_int32_t tr_inaddr;        /* incoming interface address */
68     u_int32_t tr_outaddr;       /* outgoing interface address */
69     u_int32_t tr_rmtaddr;       /* parent address in source tree */
70     u_int32_t tr_vifin;         /* input packet count on interface */
71     u_int32_t tr_vifout;        /* output packet count on interface */
72     u_int32_t tr_pktcnt;        /* total incoming packets for src-grp */
73     u_int8_t  tr_rproto;      /* routing proto deployed on router */
74     u_int8_t  tr_fttl;        /* ttl required to forward on outvif */
75     u_int8_t  tr_smask;       /* subnet mask for src addr */
76     u_int8_t  tr_rflags;      /* forwarding error codes */
77 };
78
79 /* defs within mtrace */
80 #define TR_QUERY 1
81 #define TR_RESP 2
82
83 /* fields for tr_rflags (forwarding error codes) */
84 #define TR_NO_ERR   0
85 #define TR_WRONG_IF 1
86 #define TR_PRUNED   2
87 #define TR_OPRUNED  3
88 #define TR_SCOPED   4
89 #define TR_NO_RTE   5
90 #define TR_NO_FWD   7
91 #define TR_NO_SPACE 0x81
92 #define TR_OLD_ROUTER   0x82
93
94 /* fields for tr_rproto (routing protocol) */
95 #define TR_PROTO_DVMRP  1
96 #define TR_PROTO_MOSPF  2
97 #define TR_PROTO_PIM    3
98 #define TR_PROTO_CBT    4
99
100 /* igmpv3 report types */
101 static struct tok igmpv3report2str[] = {
102         { 1,    "is_in" },
103         { 2,    "is_ex" },
104         { 3,    "to_in" },
105         { 4,    "to_ex" },
106         { 5,    "allow" },
107         { 6,    "block" },
108         { 0,    NULL }
109 };
110
111 static void
112 print_mtrace(register const u_char *bp, register u_int len)
113 {
114     register const struct tr_query *tr = (const struct tr_query *)(bp + 8);
115
116     TCHECK(*tr);
117     if (len < 8 + sizeof (struct tr_query)) {
118         (void)printf(" [invalid len %d]", len);
119         return;
120     }
121     printf("mtrace %u: %s to %s reply-to %s",
122         TR_GETQID(EXTRACT_32BITS(&tr->tr_rttlqid)),
123         ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
124         ipaddr_string(&tr->tr_raddr));
125     if (IN_CLASSD(EXTRACT_32BITS(&tr->tr_raddr)))
126         printf(" with-ttl %d", TR_GETTTL(EXTRACT_32BITS(&tr->tr_rttlqid)));
127     return;
128 trunc:
129     (void)printf("[|igmp]");
130     return;
131 }
132
133 static void
134 print_mresp(register const u_char *bp, register u_int len)
135 {
136     register const struct tr_query *tr = (const struct tr_query *)(bp + 8);
137
138     TCHECK(*tr);
139     if (len < 8 + sizeof (struct tr_query)) {
140         (void)printf(" [invalid len %d]", len);
141         return;
142     }
143     printf("mresp %lu: %s to %s reply-to %s",
144         (u_long)TR_GETQID(EXTRACT_32BITS(&tr->tr_rttlqid)),
145         ipaddr_string(&tr->tr_src), ipaddr_string(&tr->tr_dst),
146         ipaddr_string(&tr->tr_raddr));
147     if (IN_CLASSD(EXTRACT_32BITS(&tr->tr_raddr)))
148         printf(" with-ttl %d", TR_GETTTL(EXTRACT_32BITS(&tr->tr_rttlqid)));
149     return;
150 trunc:
151     (void)printf("[|igmp]");
152     return;
153 }
154
155 static void
156 print_igmpv3_report(register const u_char *bp, register u_int len)
157 {
158     u_int group, nsrcs, ngroups;
159     register u_int i, j;
160
161     /* Minimum len is 16, and should be a multiple of 4 */
162     if (len < 16 || len & 0x03) {
163         (void)printf(" [invalid len %d]", len);
164         return;
165     }
166     TCHECK2(bp[6], 2);
167     ngroups = EXTRACT_16BITS(&bp[6]);
168     (void)printf(", %d group record(s)", ngroups);
169     if (vflag > 0) {
170         /* Print the group records */
171         group = 8;
172         for (i=0; i<ngroups; i++) {
173             if (len < group+8) {
174                 (void)printf(" [invalid number of groups]");
175                 return;
176             }
177             TCHECK2(bp[group+4], 4);
178             (void)printf(" [gaddr %s", ipaddr_string(&bp[group+4]));
179             (void)printf(" %s", tok2str(igmpv3report2str, " [v3-report-#%d]",
180                                                                 bp[group]));
181             nsrcs = EXTRACT_16BITS(&bp[group+2]);
182             /* Check the number of sources and print them */
183             if (len < group+8+(nsrcs<<2)) {
184                 (void)printf(" [invalid number of sources %d]", nsrcs);
185                 return;
186             }
187             if (vflag == 1)
188                 (void)printf(", %d source(s)", nsrcs);
189             else {
190                 /* Print the sources */
191                 (void)printf(" {");
192                 for (j=0; j<nsrcs; j++) {
193                     TCHECK2(bp[group+8+(j<<2)], 4);
194                     (void)printf(" %s", ipaddr_string(&bp[group+8+(j<<2)]));
195                 }
196                 (void)printf(" }");
197             }
198             /* Next group record */
199             group += 8 + (nsrcs << 2);
200             (void)printf("]");
201         }
202     }
203     return;
204 trunc:
205     (void)printf("[|igmp]");
206     return;
207 }
208
209 static void
210 print_igmpv3_query(register const u_char *bp, register u_int len)
211 {
212     u_int mrc;
213     int mrt;
214     u_int nsrcs;
215     register u_int i;
216
217     (void)printf(" v3");
218     /* Minimum len is 12, and should be a multiple of 4 */
219     if (len < 12 || len & 0x03) {
220         (void)printf(" [invalid len %d]", len);
221         return;
222     }
223     TCHECK(bp[1]);
224     mrc = bp[1];
225     if (mrc < 128) {
226         mrt = mrc;
227     } else {
228         mrt = ((mrc & 0x0f) | 0x10) << (((mrc & 0x70) >> 4) + 3);
229     }
230     if (mrc != 100) {
231         (void)printf(" [max resp time ");
232         relts_print(mrt);
233         (void)printf("]");
234     }
235     TCHECK2(bp[4], 4);
236     if (EXTRACT_32BITS(&bp[4]) == 0)
237         return;
238     (void)printf(" [gaddr %s", ipaddr_string(&bp[4]));
239     TCHECK2(bp[10], 2);
240     nsrcs = EXTRACT_16BITS(&bp[10]);
241     if (nsrcs > 0) {
242         if (len < 12 + (nsrcs << 2))
243             (void)printf(" [invalid number of sources]");
244         else if (vflag > 1) {
245             (void)printf(" {");
246             for (i=0; i<nsrcs; i++) {
247                 TCHECK2(bp[12+(i<<2)], 4);
248                 (void)printf(" %s", ipaddr_string(&bp[12+(i<<2)]));
249             }
250             (void)printf(" }");
251         } else
252             (void)printf(", %d source(s)", nsrcs);
253     }
254     (void)printf("]");
255     return;
256 trunc:
257     (void)printf("[|igmp]");
258     return;
259 }
260
261 void
262 igmp_print(register const u_char *bp, register u_int len)
263 {
264     if (qflag) {
265         (void)printf("igmp");
266         return;
267     }
268
269     TCHECK(bp[0]);
270     switch (bp[0]) {
271     case 0x11:
272         (void)printf("igmp query");
273         if (len >= 12)
274             print_igmpv3_query(bp, len);
275         else {
276             TCHECK(bp[1]);
277             if (bp[1]) {
278                 (void)printf(" v2");
279                 if (bp[1] != 100)
280                     (void)printf(" [max resp time %d]", bp[1]);
281             } else
282                 (void)printf(" v1");
283             TCHECK2(bp[4], 4);
284             if (EXTRACT_32BITS(&bp[4]))
285                 (void)printf(" [gaddr %s]", ipaddr_string(&bp[4]));
286             if (len != 8)
287                 (void)printf(" [len %d]", len);
288         }
289         break;
290     case 0x12:
291         TCHECK2(bp[4], 4);
292         (void)printf("igmp v1 report %s", ipaddr_string(&bp[4]));
293         if (len != 8)
294             (void)printf(" [len %d]", len);
295         break;
296     case 0x16:
297         TCHECK2(bp[4], 4);
298         (void)printf("igmp v2 report %s", ipaddr_string(&bp[4]));
299         break;
300     case 0x22:
301         (void)printf("igmp v3 report");
302         print_igmpv3_report(bp, len);
303         break;
304     case 0x17:
305         TCHECK2(bp[4], 4);
306         (void)printf("igmp leave %s", ipaddr_string(&bp[4]));
307         break;
308     case 0x13:
309         (void)printf("igmp dvmrp");
310         if (len < 8)
311             (void)printf(" [len %d]", len);
312         else
313             dvmrp_print(bp, len);
314         break;
315     case 0x14:
316         (void)printf("igmp pimv1");
317         pimv1_print(bp, len);
318         break;
319     case 0x1e:
320         print_mresp(bp, len);
321         break;
322     case 0x1f:
323         print_mtrace(bp, len);
324         break;
325     default:
326         (void)printf("igmp-%d", bp[0]);
327         break;
328     }
329
330     if (vflag && TTEST2(bp[0], len)) {
331         /* Check the IGMP checksum */
332         if (in_cksum((const u_short*)bp, len, 0))
333             printf(" bad igmp cksum %x!", EXTRACT_16BITS(&bp[2]));
334     }
335     return;
336 trunc:
337     fputs("[|igmp]", stdout);
338 }
339 #endif