]> The Tcpdump Group git mirrors - tcpdump/blob - print-pim.c
Switch to config.h instead of passing defines in DEFS.
[tcpdump] / print-pim.c
1 /*
2 * Copyright (c) 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-pim.c,v 1.13 1999-11-21 09:36:59 fenner 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/time.h>
33 #include <sys/socket.h>
34
35 #include <netinet/in.h>
36 #include <netinet/in_systm.h>
37 #include <netinet/ip.h>
38 #include <netinet/ip_var.h>
39 #include <netinet/udp.h>
40 #include <netinet/udp_var.h>
41 #include <netinet/tcp.h>
42
43 /*
44 * XXX: We consider a case where IPv6 is not ready yet for portability,
45 * but PIM dependent defintions should be independent of IPv6...
46 */
47 #ifdef INET6
48 #include <netinet6/pim6.h>
49 #else
50 struct pim {
51 #if defined(WORDS_BIGENDIAN) || (defined(BYTE_ORDER) && (BYTE_ORDER == LITTLE_ENDIAN))
52 u_int pim_type:4, /* the PIM message type, currently they are:
53 * Hello, Register, Register-Stop, Join/Prune,
54 * Bootstrap, Assert, Graft (PIM-DM only),
55 * Graft-Ack (PIM-DM only), C-RP-Adv
56 */
57 pim_ver:4; /* PIM version number; 2 for PIMv2 */
58 #else
59 u_int pim_ver:4, /* PIM version */
60 pim_type:4; /* PIM type */
61 #endif
62 u_char pim_rsv; /* Reserved */
63 u_short pim_cksum; /* IP style check sum */
64 };
65 #endif
66
67
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <unistd.h>
71
72 #include "interface.h"
73 #include "addrtoname.h"
74
75 static void pimv2_print(register const u_char *bp, register u_int len);
76
77 void
78 igmp_pim_print(register const u_char *bp, register u_int len)
79 {
80 register const u_char *ep;
81 register u_char type;
82
83 ep = (const u_char *)snapend;
84 if (bp >= ep)
85 return;
86
87 type = bp[1];
88
89 switch (type) {
90 case 0:
91 (void)printf(" Query");
92 break;
93
94 case 1:
95 (void)printf(" Register");
96 break;
97
98 case 2:
99 (void)printf(" Register-Stop");
100 break;
101
102 case 3:
103 (void)printf(" Join/Prune");
104 break;
105
106 case 4:
107 (void)printf(" RP-reachable");
108 break;
109
110 case 5:
111 (void)printf(" Assert");
112 break;
113
114 case 6:
115 (void)printf(" Graft");
116 break;
117
118 case 7:
119 (void)printf(" Graft-ACK");
120 break;
121
122 case 8:
123 (void)printf(" Mode");
124 break;
125
126 default:
127 (void)printf(" [type %d]", type);
128 break;
129 }
130 }
131
132 void
133 pim_print(register const u_char *bp, register u_int len)
134 {
135 register const u_char *ep;
136 register struct pim *pim = (struct pim *)bp;
137
138 ep = (const u_char *)snapend;
139 if (bp >= ep)
140 return;
141 #ifdef notyet /* currently we see only version and type */
142 TCHECK(pim->pim_rsv);
143 #endif
144
145 switch(pim->pim_ver) {
146 case 2: /* avoid hardcoding? */
147 (void)printf("v2");
148 pimv2_print(bp, len);
149 break;
150 default:
151 (void)printf("v%d", pim->pim_ver);
152 break;
153 }
154 return;
155 }
156
157 enum pimv2_addrtype {
158 pimv2_unicast, pimv2_group, pimv2_source
159 };
160 #if 0
161 static char *addrtypestr[] = {
162 "unicast", "group", "source"
163 };
164 #endif
165
166 static int
167 pimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent)
168 {
169 const u_char *ep;
170 int af;
171 char *afstr;
172 int len;
173
174 ep = (const u_char *)snapend;
175 if (bp >= ep)
176 return -1;
177
178 switch (bp[0]) {
179 case 1:
180 af = AF_INET;
181 afstr = "IPv4";
182 break;
183 #ifdef INET6
184 case 2:
185 af = AF_INET6;
186 afstr = "IPv6";
187 break;
188 #endif
189 default:
190 return -1;
191 }
192
193 if (bp[1] != 0)
194 return -1;
195
196 switch (at) {
197 case pimv2_unicast:
198 if (af == AF_INET) {
199 len = 4;
200 if (bp + 2 + len > ep)
201 return -1;
202 if (!silent)
203 (void)printf("%s", ipaddr_string(bp + 2));
204 }
205 #ifdef INET6
206 else if (af == AF_INET6) {
207 len = 16;
208 if (bp + 2 + len > ep)
209 return -1;
210 if (!silent)
211 (void)printf("%s", ip6addr_string(bp + 2));
212 }
213 #endif
214 return 2 + len;
215 case pimv2_group:
216 if (af == AF_INET) {
217 len = 4;
218 if (bp + 4 + len > ep)
219 return -1;
220 if (!silent)
221 (void)printf("%s/%u", ipaddr_string(bp + 4), bp[3]);
222 }
223 #ifdef INET6
224 else if (af == AF_INET6) {
225 len = 16;
226 if (bp + 4 + len > ep)
227 return -1;
228 if (!silent)
229 (void)printf("%s/%u", ip6addr_string(bp + 4), bp[3]);
230 }
231 #endif
232 return 4 + len;
233 case pimv2_source:
234 if (af == AF_INET) {
235 len = 4;
236 if (bp + 4 + len > ep)
237 return -1;
238 if (!silent)
239 (void)printf("%s/%u", ipaddr_string(bp + 4), bp[3]);
240 }
241 #ifdef INET6
242 else if (af == AF_INET6) {
243 len = 16;
244 if (bp + 4 + len > ep)
245 return -1;
246 if (!silent)
247 (void)printf("%s/%u", ip6addr_string(bp + 4), bp[3]);
248 }
249 #endif
250 if (vflag && bp[2] && !silent) {
251 (void)printf("(%s%s%s)",
252 bp[2] & 0x04 ? "S" : "",
253 bp[2] & 0x02 ? "W" : "",
254 bp[2] & 0x01 ? "R" : "");
255 }
256 return 4 + len;
257 default:
258 return -1;
259 }
260 }
261
262 static void
263 pimv2_print(register const u_char *bp, register u_int len)
264 {
265 register const u_char *ep;
266 register struct pim *pim = (struct pim *)bp;
267 int advance;
268
269 ep = (const u_char *)snapend;
270 if (bp >= ep)
271 return;
272 #ifdef notyet /* currently we see only version and type */
273 TCHECK(pim->pim_rsv);
274 #endif
275
276 switch (pim->pim_type) {
277 case 0:
278 {
279 u_int16_t otype, olen;
280 (void)printf(" Hello");
281 bp += 4;
282 while (bp < ep) {
283 otype = ntohs(*(u_int16_t *)(bp + 0));
284 olen = ntohs(*(u_int16_t *)(bp + 2));
285 if (otype == 1 && olen == 2 && bp + 4 + olen <= ep) {
286 u_int16_t value;
287 (void)printf(" holdtime=");
288 value = ntohs(*(u_int16_t *)(bp + 4));
289 if (value == 0xffff)
290 (void)printf("infty");
291 else
292 (void)printf("%u", value);
293 bp += 4 + olen;
294 } else
295 break;
296 }
297 break;
298 }
299
300 case 1:
301 {
302 struct ip *ip;
303
304 (void)printf(" Register");
305 if (vflag && bp + 8 <= ep) {
306 (void)printf(" %s%s", bp[4] & 0x80 ? "B" : "",
307 bp[4] & 0x40 ? "N" : "");
308 }
309 bp += 8; len -= 8;
310
311 /* encapsulated multicast packet */
312 if (bp >= ep)
313 break;
314 ip = (struct ip *)bp;
315 switch(ip->ip_v) {
316 case 4: /* IPv4 */
317 printf(" ");
318 ip_print(bp, len);
319 break;
320 #ifdef INET6
321 case 6: /* IPv6 */
322 printf(" ");
323 ip6_print(bp, len);
324 break;
325 #endif
326 default:
327 (void)printf(" IP ver %d", ip->ip_v);
328 break;
329 }
330 break;
331 }
332
333 case 2:
334 (void)printf(" Register-Stop");
335 bp += 4; len -= 4;
336 if (bp >= ep)
337 break;
338 (void)printf(" group=");
339 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
340 (void)printf("...");
341 break;
342 }
343 bp += advance; len -= advance;
344 if (bp >= ep)
345 break;
346 (void)printf(" source=");
347 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
348 (void)printf("...");
349 break;
350 }
351 bp += advance; len -= advance;
352 break;
353
354 case 3:
355 case 6:
356 case 7:
357 {
358 u_int8_t ngroup;
359 u_int16_t holdtime;
360 u_int16_t njoin;
361 u_int16_t nprune;
362 int i, j;
363
364 switch (pim->pim_type) {
365 case 3:
366 (void)printf(" Join/Prune");
367 break;
368 case 6:
369 (void)printf(" Graft");
370 break;
371 case 7:
372 (void)printf(" Graft-ACK");
373 break;
374 }
375 bp += 4; len -= 4;
376 if (pim->pim_type != 7) { /*not for Graft-ACK*/
377 if (bp >= ep)
378 break;
379 (void)printf(" upstream-neighbor=");
380 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
381 (void)printf("...");
382 break;
383 }
384 bp += advance; len -= advance;
385 }
386 if (bp + 4 > ep)
387 break;
388 ngroup = bp[1];
389 holdtime = ntohs(*(u_int16_t *)(bp + 2));
390 (void)printf(" groups=%u", ngroup);
391 if (pim->pim_type != 7) { /*not for Graft-ACK*/
392 (void)printf(" holdtime=");
393 if (holdtime == 0xffff)
394 (void)printf("infty");
395 else
396 (void)printf("%u", holdtime);
397 }
398 bp += 4; len -= 4;
399 for (i = 0; i < ngroup; i++) {
400 if (bp >= ep)
401 goto jp_done;
402 (void)printf(" (group%d: ", i);
403 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
404 (void)printf("...)");
405 goto jp_done;
406 }
407 bp += advance; len -= advance;
408 if (bp + 4 > ep) {
409 (void)printf("...)");
410 goto jp_done;
411 }
412 njoin = ntohs(*(u_int16_t *)(bp + 0));
413 nprune = ntohs(*(u_int16_t *)(bp + 2));
414 (void)printf(" join=%u", njoin);
415 bp += 4; len -= 4;
416 for (j = 0; j < njoin; j++) {
417 (void)printf(" ");
418 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) {
419 (void)printf("...)");
420 goto jp_done;
421 }
422 bp += advance; len -= advance;
423 }
424 (void)printf(" prune=%u", nprune);
425 for (j = 0; j < nprune; j++) {
426 (void)printf(" ");
427 if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) {
428 (void)printf("...)");
429 goto jp_done;
430 }
431 bp += advance; len -= advance;
432 }
433 (void)printf(")");
434 }
435 jp_done:
436 break;
437 }
438
439 case 4:
440 {
441 int i, j, frpcnt;
442
443 (void)printf(" Bootstrap");
444 bp += 4;
445
446 /* Fragment Tag, Hash Mask len, and BSR-priority */
447 if (bp + sizeof(u_int16_t) >= ep) break;
448 (void)printf(" tag=%x", ntohs(*(u_int16_t *)bp));
449 bp += sizeof(u_int16_t);
450 if (bp >= ep) break;
451 (void)printf(" hashmlen=%d", bp[0]);
452 if (bp + 1 >= ep) break;
453 (void)printf(" BSRprio=%d", bp[1]);
454 bp += 2;
455
456 /* Encoded-Unicast-BSR-Address */
457 if (bp >= ep) break;
458 (void)printf(" BSR=");
459 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
460 (void)printf("...");
461 break;
462 }
463 bp += advance;
464
465 for (i = 0; bp < ep; i++) {
466 /* Encoded-Group Address */
467 (void)printf(" (group%d: ", i);
468 if ((advance = pimv2_addr_print(bp, pimv2_group, 0))
469 < 0) {
470 (void)printf("...)");
471 goto bs_done;
472 }
473 bp += advance;
474
475 /* RP-Count, Frag RP-Cnt, and rsvd */
476 if (bp >= ep) {
477 (void)printf("...)");
478 goto bs_done;
479 }
480 (void)printf(" RPcnt=%d", frpcnt = bp[0]);
481 if (bp + 1 >= ep) {
482 (void)printf("...)");
483 goto bs_done;
484 }
485 (void)printf(" FRPcnt=%d", bp[1]);
486 bp += 4;
487
488 for (j = 0; j < frpcnt && bp < ep; j++) {
489 /* each RP info */
490 (void)printf(" RP%d=", j);
491 if ((advance = pimv2_addr_print(bp,
492 pimv2_unicast,
493 0)) < 0) {
494 (void)printf("...)");
495 goto bs_done;
496 }
497 bp += advance;
498
499 if (bp + 1 >= ep) {
500 (void)printf("...)");
501 goto bs_done;
502 }
503 (void)printf(",holdtime=%d",
504 ntohs(*(u_int16_t *)bp));
505 if (bp + 2 >= ep) {
506 (void)printf("...)");
507 goto bs_done;
508 }
509 (void)printf(",prio=%d", bp[2]);
510 bp += 4;
511 }
512 (void)printf(")");
513 }
514 bs_done:
515 break;
516 }
517 case 5:
518 (void)printf(" Assert");
519 bp += 4; len -= 4;
520 if (bp >= ep)
521 break;
522 (void)printf(" group=");
523 if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
524 (void)printf("...");
525 break;
526 }
527 bp += advance; len -= advance;
528 if (bp >= ep)
529 break;
530 (void)printf(" src=");
531 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
532 (void)printf("...");
533 break;
534 }
535 bp += advance; len -= advance;
536 if (bp + 8 > ep)
537 break;
538 if (ntohl(*(u_int32_t *)bp) & 0x80000000)
539 (void)printf(" RPT");
540 (void)printf(" pref=%u", ntohl(*(u_int32_t *)bp & 0x7fffffff));
541 (void)printf(" metric=%u", ntohl(*(u_int32_t *)(bp + 4)));
542 break;
543
544 case 8:
545 {
546 int i, pfxcnt;
547
548 (void)printf(" Candidate-RP-Advertisement");
549 bp += 4;
550
551 /* Prefix-Cnt, Priority, and Holdtime */
552 if (bp >= ep) break;
553 (void)printf(" prefix-cnt=%d", bp[0]);
554 pfxcnt = bp[0];
555 if (bp + 1 >= ep) break;
556 (void)printf(" prio=%d", bp[1]);
557 if (bp + 3 >= ep) break;
558 (void)printf(" holdtime=%d", ntohs(*(u_int16_t *)(bp + 2)));
559 bp += 4;
560
561 /* Encoded-Unicast-RP-Address */
562 if (bp >= ep) break;
563 (void)printf(" RP=");
564 if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
565 (void)printf("...");
566 break;
567 }
568 bp += advance;
569
570 /* Encoded-Group Addresses */
571 for (i = 0; i < pfxcnt && bp < ep; i++) {
572 (void)printf(" Group%d=", i);
573 if ((advance = pimv2_addr_print(bp, pimv2_group, 0))
574 < 0) {
575 (void)printf("...");
576 break;
577 }
578 bp += advance;
579 }
580 break;
581 }
582
583 default:
584 (void)printf(" [type %d]", pim->pim_type);
585 break;
586 }
587
588 return;
589 }