source: rtems-libbsd/freebsd/contrib/tcpdump/print-pim.c @ 8440506

4.1155-freebsd-126-freebsd-12freebsd-9.3
Last change on this file since 8440506 was 8440506, checked in by Chris Johns <chrisj@…>, on 06/15/15 at 07:42:23

Add tcpdump and libpcap.

  • Update the file builder generator to handle generator specific cflags and includes. The tcpdump and libpcap have localised headers and need specific headers paths to see them. There are also module specific flags and these need to be passed to the lex and yacc generators.
  • Add the tcpdump support.
  • Property mode set to 100644
File size: 29.6 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Copyright (c) 1995, 1996
5 *      The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that: (1) source code distributions
9 * retain the above copyright notice and this paragraph in its entirety, (2)
10 * distributions including binary code include the above copyright notice and
11 * this paragraph in its entirety in the documentation or other materials
12 * provided with the distribution, and (3) all advertising materials mentioning
13 * features or use of this software display the following acknowledgement:
14 * ``This product includes software developed by the University of California,
15 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16 * the University nor the names of its contributors may be used to endorse
17 * or promote products derived from this software without specific prior
18 * written permission.
19 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 *
23 * $FreeBSD$
24 */
25
26#ifndef lint
27static const char rcsid[] _U_ =
28    "@(#) $Header: /tcpdump/master/tcpdump/print-pim.c,v 1.49 2006-02-13 01:31:35 hannes Exp $ (LBL)";
29#endif
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include <tcpdump-stdinc.h>
36
37#include <stdio.h>
38#include <stdlib.h>
39
40#include "interface.h"
41#include "addrtoname.h"
42#include "extract.h"
43
44#include "ip.h"
45
46#define PIMV2_TYPE_HELLO         0
47#define PIMV2_TYPE_REGISTER      1
48#define PIMV2_TYPE_REGISTER_STOP 2
49#define PIMV2_TYPE_JOIN_PRUNE    3
50#define PIMV2_TYPE_BOOTSTRAP     4
51#define PIMV2_TYPE_ASSERT        5
52#define PIMV2_TYPE_GRAFT         6
53#define PIMV2_TYPE_GRAFT_ACK     7
54#define PIMV2_TYPE_CANDIDATE_RP  8
55#define PIMV2_TYPE_PRUNE_REFRESH 9
56
57static struct tok pimv2_type_values[] = {
58    { PIMV2_TYPE_HELLO,         "Hello" },
59    { PIMV2_TYPE_REGISTER,      "Register" },
60    { PIMV2_TYPE_REGISTER_STOP, "Register Stop" },
61    { PIMV2_TYPE_JOIN_PRUNE,    "Join / Prune" },
62    { PIMV2_TYPE_BOOTSTRAP,     "Bootstrap" },
63    { PIMV2_TYPE_ASSERT,        "Assert" },
64    { PIMV2_TYPE_GRAFT,         "Graft" },
65    { PIMV2_TYPE_GRAFT_ACK,     "Graft Acknowledgement" },
66    { PIMV2_TYPE_CANDIDATE_RP,  "Candidate RP Advertisement" },
67    { PIMV2_TYPE_PRUNE_REFRESH, "Prune Refresh" },
68    { 0, NULL}
69};
70
71#define PIMV2_HELLO_OPTION_HOLDTIME             1
72#define PIMV2_HELLO_OPTION_LANPRUNEDELAY        2
73#define PIMV2_HELLO_OPTION_DR_PRIORITY_OLD     18
74#define PIMV2_HELLO_OPTION_DR_PRIORITY         19
75#define PIMV2_HELLO_OPTION_GENID               20
76#define PIMV2_HELLO_OPTION_REFRESH_CAP         21
77#define PIMV2_HELLO_OPTION_BIDIR_CAP           22
78#define PIMV2_HELLO_OPTION_ADDRESS_LIST        24
79#define PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD 65001
80
81static struct tok pimv2_hello_option_values[] = {
82    { PIMV2_HELLO_OPTION_HOLDTIME,         "Hold Time" },
83    { PIMV2_HELLO_OPTION_LANPRUNEDELAY,    "LAN Prune Delay" },
84    { PIMV2_HELLO_OPTION_DR_PRIORITY_OLD,  "DR Priority (Old)" },
85    { PIMV2_HELLO_OPTION_DR_PRIORITY,      "DR Priority" },
86    { PIMV2_HELLO_OPTION_GENID,            "Generation ID" },
87    { PIMV2_HELLO_OPTION_REFRESH_CAP,      "State Refresh Capability" },
88    { PIMV2_HELLO_OPTION_BIDIR_CAP,        "Bi-Directional Capability" },
89    { PIMV2_HELLO_OPTION_ADDRESS_LIST,     "Address List" },
90    { PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD, "Address List (Old)" },
91    { 0, NULL}
92};
93
94#define PIMV2_REGISTER_FLAG_LEN      4
95#define PIMV2_REGISTER_FLAG_BORDER 0x80000000
96#define PIMV2_REGISTER_FLAG_NULL   0x40000000
97
98static struct tok pimv2_register_flag_values[] = {
99    { PIMV2_REGISTER_FLAG_BORDER, "Border" },
100    { PIMV2_REGISTER_FLAG_NULL, "Null" },
101    { 0, NULL}
102};   
103
104/*
105 * XXX: We consider a case where IPv6 is not ready yet for portability,
106 * but PIM dependent defintions should be independent of IPv6...
107 */
108
109struct pim {
110        u_int8_t pim_typever;
111                        /* upper 4bit: PIM version number; 2 for PIMv2 */
112                        /* lower 4bit: the PIM message type, currently they are:
113                         * Hello, Register, Register-Stop, Join/Prune,
114                         * Bootstrap, Assert, Graft (PIM-DM only),
115                         * Graft-Ack (PIM-DM only), C-RP-Adv
116                         */
117#define PIM_VER(x)      (((x) & 0xf0) >> 4)
118#define PIM_TYPE(x)     ((x) & 0x0f)
119        u_char  pim_rsv;        /* Reserved */
120        u_short pim_cksum;      /* IP style check sum */
121};
122
123static void pimv2_print(register const u_char *bp, register u_int len, u_int cksum);
124
125static void
126pimv1_join_prune_print(register const u_char *bp, register u_int len)
127{
128        int maddrlen, addrlen, ngroups, njoin, nprune;
129        int njp;
130
131        /* If it's a single group and a single source, use 1-line output. */
132        if (TTEST2(bp[0], 30) && bp[11] == 1 &&
133            ((njoin = EXTRACT_16BITS(&bp[20])) + EXTRACT_16BITS(&bp[22])) == 1) {
134                int hold;
135
136                (void)printf(" RPF %s ", ipaddr_string(bp));
137                hold = EXTRACT_16BITS(&bp[6]);
138                if (hold != 180) {
139                        (void)printf("Hold ");
140                        relts_print(hold);
141                }
142                (void)printf("%s (%s/%d, %s", njoin ? "Join" : "Prune",
143                ipaddr_string(&bp[26]), bp[25] & 0x3f,
144                ipaddr_string(&bp[12]));
145                if (EXTRACT_32BITS(&bp[16]) != 0xffffffff)
146                        (void)printf("/%s", ipaddr_string(&bp[16]));
147                (void)printf(") %s%s %s",
148                    (bp[24] & 0x01) ? "Sparse" : "Dense",
149                    (bp[25] & 0x80) ? " WC" : "",
150                    (bp[25] & 0x40) ? "RP" : "SPT");
151                return;
152        }
153
154        TCHECK2(bp[0], sizeof(struct in_addr));
155        if (vflag > 1)
156                (void)printf("\n");
157        (void)printf(" Upstream Nbr: %s", ipaddr_string(bp));
158        TCHECK2(bp[6], 2);
159        if (vflag > 1)
160                (void)printf("\n");
161        (void)printf(" Hold time: ");
162        relts_print(EXTRACT_16BITS(&bp[6]));
163        if (vflag < 2)
164                return;
165        bp += 8;
166        len -= 8;
167
168        TCHECK2(bp[0], 4);
169        maddrlen = bp[1];
170        addrlen = bp[2];
171        ngroups = bp[3];
172        bp += 4;
173        len -= 4;
174        while (ngroups--) {
175                /*
176                 * XXX - does the address have length "addrlen" and the
177                 * mask length "maddrlen"?
178                 */
179                TCHECK2(bp[0], sizeof(struct in_addr));
180                (void)printf("\n\tGroup: %s", ipaddr_string(bp));
181                TCHECK2(bp[4], sizeof(struct in_addr));
182                if (EXTRACT_32BITS(&bp[4]) != 0xffffffff)
183                        (void)printf("/%s", ipaddr_string(&bp[4]));
184                TCHECK2(bp[8], 4);
185                njoin = EXTRACT_16BITS(&bp[8]);
186                nprune = EXTRACT_16BITS(&bp[10]);
187                (void)printf(" joined: %d pruned: %d", njoin, nprune);
188                bp += 12;
189                len -= 12;
190                for (njp = 0; njp < (njoin + nprune); njp++) {
191                        const char *type;
192
193                        if (njp < njoin)
194                                type = "Join ";
195                        else
196                                type = "Prune";
197                        TCHECK2(bp[0], 6);
198                        (void)printf("\n\t%s %s%s%s%s/%d", type,
199                            (bp[0] & 0x01) ? "Sparse " : "Dense ",
200                            (bp[1] & 0x80) ? "WC " : "",
201                            (bp[1] & 0x40) ? "RP " : "SPT ",
202                        ipaddr_string(&bp[2]), bp[1] & 0x3f);
203                        bp += 6;
204                        len -= 6;
205                }
206        }
207        return;
208trunc:
209        (void)printf("[|pim]");
210        return;
211}
212
213void
214pimv1_print(register const u_char *bp, register u_int len)
215{
216        register const u_char *ep;
217        register u_char type;
218
219        ep = (const u_char *)snapend;
220        if (bp >= ep)
221                return;
222
223        TCHECK(bp[1]);
224        type = bp[1];
225
226        switch (type) {
227        case 0:
228                (void)printf(" Query");
229                if (TTEST(bp[8])) {
230                        switch (bp[8] >> 4) {
231                        case 0:
232                                (void)printf(" Dense-mode");
233                                break;
234                        case 1:
235                                (void)printf(" Sparse-mode");
236                                break;
237                        case 2:
238                                (void)printf(" Sparse-Dense-mode");
239                                break;
240                        default:
241                                (void)printf(" mode-%d", bp[8] >> 4);
242                                break;
243                        }
244                }
245                if (vflag) {
246                        TCHECK2(bp[10],2);
247                        (void)printf(" (Hold-time ");
248                        relts_print(EXTRACT_16BITS(&bp[10]));
249                        (void)printf(")");
250                }
251                break;
252
253        case 1:
254                (void)printf(" Register");
255                TCHECK2(bp[8], 20);                     /* ip header */
256                (void)printf(" for %s > %s", ipaddr_string(&bp[20]),
257                    ipaddr_string(&bp[24]));
258                break;
259        case 2:
260                (void)printf(" Register-Stop");
261                TCHECK2(bp[12], sizeof(struct in_addr));
262                (void)printf(" for %s > %s", ipaddr_string(&bp[8]),
263                    ipaddr_string(&bp[12]));
264                break;
265        case 3:
266                (void)printf(" Join/Prune");
267                if (vflag)
268                        pimv1_join_prune_print(&bp[8], len - 8);
269                break;
270        case 4:
271                (void)printf(" RP-reachable");
272                if (vflag) {
273                        TCHECK2(bp[22], 2);
274                        (void)printf(" group %s",
275                        ipaddr_string(&bp[8]));
276                        if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)
277                                (void)printf("/%s", ipaddr_string(&bp[12]));
278                        (void)printf(" RP %s hold ", ipaddr_string(&bp[16]));
279                        relts_print(EXTRACT_16BITS(&bp[22]));
280                }
281                break;
282        case 5:
283                (void)printf(" Assert");
284                TCHECK2(bp[16], sizeof(struct in_addr));
285                (void)printf(" for %s > %s", ipaddr_string(&bp[16]),
286                    ipaddr_string(&bp[8]));
287                if (EXTRACT_32BITS(&bp[12]) != 0xffffffff)
288                        (void)printf("/%s", ipaddr_string(&bp[12]));
289                TCHECK2(bp[24], 4);
290                (void)printf(" %s pref %d metric %d",
291                    (bp[20] & 0x80) ? "RP-tree" : "SPT",
292                EXTRACT_32BITS(&bp[20]) & 0x7fffffff,
293                EXTRACT_32BITS(&bp[24]));
294                break;
295        case 6:
296                (void)printf(" Graft");
297                if (vflag)
298                        pimv1_join_prune_print(&bp[8], len - 8);
299                break;
300        case 7:
301                (void)printf(" Graft-ACK");
302                if (vflag)
303                        pimv1_join_prune_print(&bp[8], len - 8);
304                break;
305        case 8:
306                (void)printf(" Mode");
307                break;
308        default:
309                (void)printf(" [type %d]", type);
310                break;
311        }
312        if ((bp[4] >> 4) != 1)
313                (void)printf(" [v%d]", bp[4] >> 4);
314        return;
315
316trunc:
317        (void)printf("[|pim]");
318        return;
319}
320
321/*
322 * auto-RP is a cisco protocol, documented at
323 * ftp://ftpeng.cisco.com/ipmulticast/specs/pim-autorp-spec01.txt
324 *
325 * This implements version 1+, dated Sept 9, 1998.
326 */
327void
328cisco_autorp_print(register const u_char *bp, register u_int len)
329{
330        int type;
331        int numrps;
332        int hold;
333
334        TCHECK(bp[0]);
335        (void)printf(" auto-rp ");
336        type = bp[0];
337        switch (type) {
338        case 0x11:
339                (void)printf("candidate-advert");
340                break;
341        case 0x12:
342                (void)printf("mapping");
343                break;
344        default:
345                (void)printf("type-0x%02x", type);
346                break;
347        }
348
349        TCHECK(bp[1]);
350        numrps = bp[1];
351
352        TCHECK2(bp[2], 2);
353        (void)printf(" Hold ");
354        hold = EXTRACT_16BITS(&bp[2]);
355        if (hold)
356                relts_print(EXTRACT_16BITS(&bp[2]));
357        else
358                printf("FOREVER");
359
360        /* Next 4 bytes are reserved. */
361
362        bp += 8; len -= 8;
363
364        /*XXX skip unless -v? */
365
366        /*
367         * Rest of packet:
368         * numrps entries of the form:
369         * 32 bits: RP
370         * 6 bits: reserved
371         * 2 bits: PIM version supported, bit 0 is "supports v1", 1 is "v2".
372         * 8 bits: # of entries for this RP
373         * each entry: 7 bits: reserved, 1 bit: negative,
374         *             8 bits: mask 32 bits: source
375         * lather, rinse, repeat.
376         */
377        while (numrps--) {
378                int nentries;
379                char s;
380
381                TCHECK2(bp[0], 4);
382                (void)printf(" RP %s", ipaddr_string(bp));
383                TCHECK(bp[4]);
384                switch (bp[4] & 0x3) {
385                case 0: printf(" PIMv?");
386                        break;
387                case 1: printf(" PIMv1");
388                        break;
389                case 2: printf(" PIMv2");
390                        break;
391                case 3: printf(" PIMv1+2");
392                        break;
393                }
394                if (bp[4] & 0xfc)
395                        (void)printf(" [rsvd=0x%02x]", bp[4] & 0xfc);
396                TCHECK(bp[5]);
397                nentries = bp[5];
398                bp += 6; len -= 6;
399                s = ' ';
400                for (; nentries; nentries--) {
401                        TCHECK2(bp[0], 6);
402                        (void)printf("%c%s%s/%d", s, bp[0] & 1 ? "!" : "",
403                            ipaddr_string(&bp[2]), bp[1]);
404                        if (bp[0] & 0x02) {
405                            (void)printf(" bidir");
406                        }
407                        if (bp[0] & 0xfc) {
408                            (void)printf("[rsvd=0x%02x]", bp[0] & 0xfc);
409                        }
410                        s = ',';
411                        bp += 6; len -= 6;
412                }
413        }
414        return;
415
416trunc:
417        (void)printf("[|autorp]");
418        return;
419}
420
421void
422pim_print(register const u_char *bp, register u_int len, u_int cksum)
423{
424        register const u_char *ep;
425        register struct pim *pim = (struct pim *)bp;
426
427        ep = (const u_char *)snapend;
428        if (bp >= ep)
429                return;
430#ifdef notyet                   /* currently we see only version and type */
431        TCHECK(pim->pim_rsv);
432#endif
433
434        switch (PIM_VER(pim->pim_typever)) {
435        case 2:
436            if (!vflag) {
437                printf("PIMv%u, %s, length %u",
438                       PIM_VER(pim->pim_typever),
439                       tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)),
440                       len);
441                return;
442            } else {
443                printf("PIMv%u, length %u\n\t%s",
444                       PIM_VER(pim->pim_typever),
445                       len,
446                       tok2str(pimv2_type_values,"Unknown Type",PIM_TYPE(pim->pim_typever)));
447                pimv2_print(bp, len, cksum);
448            }
449            break;
450        default:
451                printf("PIMv%u, length %u",
452                       PIM_VER(pim->pim_typever),
453                       len);
454                break;
455        }
456        return;
457}
458
459/*
460 * PIMv2 uses encoded address representations.
461 *
462 * The last PIM-SM I-D before RFC2117 was published specified the
463 * following representation for unicast addresses.  However, RFC2117
464 * specified no encoding for unicast addresses with the unicast
465 * address length specified in the header.  Therefore, we have to
466 * guess which encoding is being used (Cisco's PIMv2 implementation
467 * uses the non-RFC encoding).  RFC2117 turns a previously "Reserved"
468 * field into a 'unicast-address-length-in-bytes' field.  We guess
469 * that it's the draft encoding if this reserved field is zero.
470 *
471 * RFC2362 goes back to the encoded format, and calls the addr length
472 * field "reserved" again.
473 *
474 * The first byte is the address family, from:
475 *
476 *    0    Reserved
477 *    1    IP (IP version 4)
478 *    2    IP6 (IP version 6)
479 *    3    NSAP
480 *    4    HDLC (8-bit multidrop)
481 *    5    BBN 1822
482 *    6    802 (includes all 802 media plus Ethernet "canonical format")
483 *    7    E.163
484 *    8    E.164 (SMDS, Frame Relay, ATM)
485 *    9    F.69 (Telex)
486 *   10    X.121 (X.25, Frame Relay)
487 *   11    IPX
488 *   12    Appletalk
489 *   13    Decnet IV
490 *   14    Banyan Vines
491 *   15    E.164 with NSAP format subaddress
492 *
493 * In addition, the second byte is an "Encoding".  0 is the default
494 * encoding for the address family, and no other encodings are currently
495 * specified.
496 *
497 */
498
499static int pimv2_addr_len;
500
501enum pimv2_addrtype {
502        pimv2_unicast, pimv2_group, pimv2_source
503};
504
505/*  0                   1                   2                   3
506 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
507 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
508 * | Addr Family   | Encoding Type |     Unicast Address           |
509 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+++++++
510 *  0                   1                   2                   3
511 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
512 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
513 * | Addr Family   | Encoding Type |   Reserved    |  Mask Len     |
514 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
515 * |                Group multicast Address                        |
516 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
517 *  0                   1                   2                   3
518 *  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
519 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
520 * | Addr Family   | Encoding Type | Rsrvd   |S|W|R|  Mask Len     |
521 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
522 * |                        Source Address                         |
523 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
524 */
525static int
526pimv2_addr_print(const u_char *bp, enum pimv2_addrtype at, int silent)
527{
528        int af;
529        int len, hdrlen;
530
531        TCHECK(bp[0]);
532
533        if (pimv2_addr_len == 0) {
534                TCHECK(bp[1]);
535                switch (bp[0]) {
536                case 1:
537                        af = AF_INET;
538                        len = sizeof(struct in_addr);
539                        break;
540#ifdef INET6
541                case 2:
542                        af = AF_INET6;
543                        len = sizeof(struct in6_addr);
544                        break;
545#endif
546                default:
547                        return -1;
548                }
549                if (bp[1] != 0)
550                        return -1;
551                hdrlen = 2;
552        } else {
553                switch (pimv2_addr_len) {
554                case sizeof(struct in_addr):
555                        af = AF_INET;
556                        break;
557#ifdef INET6
558                case sizeof(struct in6_addr):
559                        af = AF_INET6;
560                        break;
561#endif
562                default:
563                        return -1;
564                        break;
565                }
566                len = pimv2_addr_len;
567                hdrlen = 0;
568        }
569
570        bp += hdrlen;
571        switch (at) {
572        case pimv2_unicast:
573                TCHECK2(bp[0], len);
574                if (af == AF_INET) {
575                        if (!silent)
576                                (void)printf("%s", ipaddr_string(bp));
577                }
578#ifdef INET6
579                else if (af == AF_INET6) {
580                        if (!silent)
581                                (void)printf("%s", ip6addr_string(bp));
582                }
583#endif
584                return hdrlen + len;
585        case pimv2_group:
586        case pimv2_source:
587                TCHECK2(bp[0], len + 2);
588                if (af == AF_INET) {
589                        if (!silent) {
590                                (void)printf("%s", ipaddr_string(bp + 2));
591                                if (bp[1] != 32)
592                                        (void)printf("/%u", bp[1]);
593                        }
594                }
595#ifdef INET6
596                else if (af == AF_INET6) {
597                        if (!silent) {
598                                (void)printf("%s", ip6addr_string(bp + 2));
599                                if (bp[1] != 128)
600                                        (void)printf("/%u", bp[1]);
601                        }
602                }
603#endif
604                if (bp[0] && !silent) {
605                        if (at == pimv2_group) {
606                                (void)printf("(0x%02x)", bp[0]);
607                        } else {
608                                (void)printf("(%s%s%s",
609                                        bp[0] & 0x04 ? "S" : "",
610                                        bp[0] & 0x02 ? "W" : "",
611                                        bp[0] & 0x01 ? "R" : "");
612                                if (bp[0] & 0xf8) {
613                                        (void) printf("+0x%02x", bp[0] & 0xf8);
614                                }
615                                (void)printf(")");
616                        }
617                }
618                return hdrlen + 2 + len;
619        default:
620                return -1;
621        }
622trunc:
623        return -1;
624}
625
626static void
627pimv2_print(register const u_char *bp, register u_int len, u_int cksum)
628{
629        register const u_char *ep;
630        register struct pim *pim = (struct pim *)bp;
631        int advance;
632
633        ep = (const u_char *)snapend;
634        if (bp >= ep)
635                return;
636        if (ep > bp + len)
637                ep = bp + len;
638        TCHECK(pim->pim_rsv);
639        pimv2_addr_len = pim->pim_rsv;
640        if (pimv2_addr_len != 0)
641                (void)printf(", RFC2117-encoding");
642
643        printf(", cksum 0x%04x ", EXTRACT_16BITS(&pim->pim_cksum));
644        if (EXTRACT_16BITS(&pim->pim_cksum) == 0) {
645                printf("(unverified)");
646        } else {
647                printf("(%scorrect)", TTEST2(bp[0], len) && cksum ? "in" : "" );
648        }
649
650        switch (PIM_TYPE(pim->pim_typever)) {
651        case PIMV2_TYPE_HELLO:
652            {
653                u_int16_t otype, olen;
654                bp += 4;
655                while (bp < ep) {
656                        TCHECK2(bp[0], 4);
657                        otype = EXTRACT_16BITS(&bp[0]);
658                        olen = EXTRACT_16BITS(&bp[2]);
659                        TCHECK2(bp[0], 4 + olen);
660
661                        printf("\n\t  %s Option (%u), length %u, Value: ",
662                               tok2str( pimv2_hello_option_values,"Unknown",otype),
663                               otype,
664                               olen);
665                        bp += 4;
666
667                        switch (otype) {
668                        case PIMV2_HELLO_OPTION_HOLDTIME:
669                                relts_print(EXTRACT_16BITS(bp));
670                                break;
671
672                        case PIMV2_HELLO_OPTION_LANPRUNEDELAY:
673                                if (olen != 4) {
674                                        (void)printf("ERROR: Option Length != 4 Bytes (%u)", olen);
675                                } else {
676                                        char t_bit;
677                                        u_int16_t lan_delay, override_interval;
678                                        lan_delay = EXTRACT_16BITS(bp);
679                                        override_interval = EXTRACT_16BITS(bp+2);
680                                        t_bit = (lan_delay & 0x8000)? 1 : 0;
681                                        lan_delay &= ~0x8000;
682                                        (void)printf("\n\t    T-bit=%d, LAN delay %dms, Override interval %dms",
683                                        t_bit, lan_delay, override_interval);
684                                }
685                                break;
686
687                        case PIMV2_HELLO_OPTION_DR_PRIORITY_OLD:
688                        case PIMV2_HELLO_OPTION_DR_PRIORITY:
689                                switch (olen) {
690                                case 0:
691                                    printf("Bi-Directional Capability (Old)");
692                                    break;
693                                case 4:
694                                    printf("%u", EXTRACT_32BITS(bp));
695                                    break;
696                                default:
697                                    printf("ERROR: Option Length != 4 Bytes (%u)", olen);
698                                    break;
699                                }
700                                break;
701
702                        case PIMV2_HELLO_OPTION_GENID:
703                                (void)printf("0x%08x", EXTRACT_32BITS(bp));
704                                break;
705
706                        case PIMV2_HELLO_OPTION_REFRESH_CAP:
707                                (void)printf("v%d", *bp);
708                                if (*(bp+1) != 0) {
709                                    (void)printf(", interval ");
710                                    relts_print(*(bp+1));
711                                }
712                                if (EXTRACT_16BITS(bp+2) != 0) {
713                                    (void)printf(" ?0x%04x?", EXTRACT_16BITS(bp+2));
714                                }
715                                break;
716
717                        case  PIMV2_HELLO_OPTION_BIDIR_CAP:
718                                break;
719
720                        case PIMV2_HELLO_OPTION_ADDRESS_LIST_OLD:
721                        case PIMV2_HELLO_OPTION_ADDRESS_LIST:
722                                if (vflag > 1) {
723                                        const u_char *ptr = bp;
724                                        while (ptr < (bp+olen)) {
725                                                int advance;
726
727                                                printf("\n\t    ");
728                                                advance = pimv2_addr_print(ptr, pimv2_unicast, 0);
729                                                if (advance < 0) {
730                                                        printf("...");
731                                                        break;
732                                                }
733                                                ptr += advance;
734                                        }
735                                }
736                                break;
737                        default:
738                                if (vflag <= 1)
739                                    print_unknown_data(bp,"\n\t    ",olen);
740                                break;
741                        }
742                        /* do we want to see an additionally hexdump ? */
743                        if (vflag> 1)
744                            print_unknown_data(bp,"\n\t    ",olen);
745                        bp += olen;
746                }
747                break;
748            }
749
750        case PIMV2_TYPE_REGISTER:
751        {
752                struct ip *ip;
753
754                if (!TTEST2(*(bp+4), PIMV2_REGISTER_FLAG_LEN))
755                        goto trunc;
756
757                printf(", Flags [ %s ]\n\t",
758                       tok2str(pimv2_register_flag_values,
759                               "none",
760                               EXTRACT_32BITS(bp+4)));
761
762                bp += 8; len -= 8;
763                /* encapsulated multicast packet */
764                ip = (struct ip *)bp;
765                switch (IP_V(ip)) {
766                case 0: /* Null header */
767                        (void)printf("IP-Null-header %s > %s",
768                                     ipaddr_string(&ip->ip_src),
769                                     ipaddr_string(&ip->ip_dst));
770                        break;
771
772                case 4: /* IPv4 */
773                        ip_print(gndo, bp, len);
774                        break;
775#ifdef INET6
776                case 6: /* IPv6 */
777                        ip6_print(gndo, bp, len);
778                        break;
779#endif
780                default:
781                        (void)printf("IP ver %d", IP_V(ip));
782                        break;
783                }
784                break;
785        }
786
787        case PIMV2_TYPE_REGISTER_STOP:
788                bp += 4; len -= 4;
789                if (bp >= ep)
790                        break;
791                (void)printf(" group=");
792                if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
793                        (void)printf("...");
794                        break;
795                }
796                bp += advance; len -= advance;
797                if (bp >= ep)
798                        break;
799                (void)printf(" source=");
800                if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
801                        (void)printf("...");
802                        break;
803                }
804                bp += advance; len -= advance;
805                break;
806
807        case PIMV2_TYPE_JOIN_PRUNE:
808        case PIMV2_TYPE_GRAFT:
809        case PIMV2_TYPE_GRAFT_ACK:
810
811
812        /*
813         * 0                   1                   2                   3
814         *   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
815         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
816         *  |PIM Ver| Type  | Addr length   |           Checksum            |
817         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
818         *  |             Unicast-Upstream Neighbor Address                 |
819         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
820         *  |  Reserved     | Num groups    |          Holdtime             |
821         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
822         *  |            Encoded-Multicast Group Address-1                  |
823         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
824         *  |   Number of Joined  Sources   |   Number of Pruned Sources    |
825         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
826         *  |               Encoded-Joined Source Address-1                 |
827         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
828         *  |                             .                                 |
829         *  |                             .                                 |
830         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
831         *  |               Encoded-Joined Source Address-n                 |
832         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
833         *  |               Encoded-Pruned Source Address-1                 |
834         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
835         *  |                             .                                 |
836         *  |                             .                                 |
837         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
838         *  |               Encoded-Pruned Source Address-n                 |
839         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
840         *  |                           .                                   |
841         *  |                           .                                   |
842         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
843         *  |                Encoded-Multicast Group Address-n              |
844         *  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
845         */
846
847            {
848                u_int8_t ngroup;
849                u_int16_t holdtime;
850                u_int16_t njoin;
851                u_int16_t nprune;
852                int i, j;
853
854                bp += 4; len -= 4;
855                if (PIM_TYPE(pim->pim_typever) != 7) {  /*not for Graft-ACK*/
856                        if (bp >= ep)
857                                break;
858                        (void)printf(", upstream-neighbor: ");
859                        if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
860                                (void)printf("...");
861                                break;
862                        }
863                        bp += advance; len -= advance;
864                }
865                if (bp + 4 > ep)
866                        break;
867                ngroup = bp[1];
868                holdtime = EXTRACT_16BITS(&bp[2]);
869                (void)printf("\n\t  %u group(s)", ngroup);
870                if (PIM_TYPE(pim->pim_typever) != 7) {  /*not for Graft-ACK*/
871                        (void)printf(", holdtime: ");
872                        if (holdtime == 0xffff)
873                                (void)printf("infinite");
874                        else
875                                relts_print(holdtime);
876                }
877                bp += 4; len -= 4;
878                for (i = 0; i < ngroup; i++) {
879                        if (bp >= ep)
880                                goto jp_done;
881                        (void)printf("\n\t    group #%u: ", i+1);
882                        if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
883                                (void)printf("...)");
884                                goto jp_done;
885                        }
886                        bp += advance; len -= advance;
887                        if (bp + 4 > ep) {
888                                (void)printf("...)");
889                                goto jp_done;
890                        }
891                        njoin = EXTRACT_16BITS(&bp[0]);
892                        nprune = EXTRACT_16BITS(&bp[2]);
893                        (void)printf(", joined sources: %u, pruned sources: %u", njoin,nprune);
894                        bp += 4; len -= 4;
895                        for (j = 0; j < njoin; j++) {
896                                (void)printf("\n\t      joined source #%u: ",j+1);
897                                if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) {
898                                        (void)printf("...)");
899                                        goto jp_done;
900                                }
901                                bp += advance; len -= advance;
902                        }
903                        for (j = 0; j < nprune; j++) {
904                                (void)printf("\n\t      pruned source #%u: ",j+1);
905                                if ((advance = pimv2_addr_print(bp, pimv2_source, 0)) < 0) {
906                                        (void)printf("...)");
907                                        goto jp_done;
908                                }
909                                bp += advance; len -= advance;
910                        }
911                }
912        jp_done:
913                break;
914            }
915
916        case PIMV2_TYPE_BOOTSTRAP:
917        {
918                int i, j, frpcnt;
919                bp += 4;
920
921                /* Fragment Tag, Hash Mask len, and BSR-priority */
922                if (bp + sizeof(u_int16_t) >= ep) break;
923                (void)printf(" tag=%x", EXTRACT_16BITS(bp));
924                bp += sizeof(u_int16_t);
925                if (bp >= ep) break;
926                (void)printf(" hashmlen=%d", bp[0]);
927                if (bp + 1 >= ep) break;
928                (void)printf(" BSRprio=%d", bp[1]);
929                bp += 2;
930
931                /* Encoded-Unicast-BSR-Address */
932                if (bp >= ep) break;
933                (void)printf(" BSR=");
934                if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
935                        (void)printf("...");
936                        break;
937                }
938                bp += advance;
939
940                for (i = 0; bp < ep; i++) {
941                        /* Encoded-Group Address */
942                        (void)printf(" (group%d: ", i);
943                        if ((advance = pimv2_addr_print(bp, pimv2_group, 0))
944                            < 0) {
945                                (void)printf("...)");
946                                goto bs_done;
947                        }
948                        bp += advance;
949
950                        /* RP-Count, Frag RP-Cnt, and rsvd */
951                        if (bp >= ep) {
952                                (void)printf("...)");
953                                goto bs_done;
954                        }
955                        (void)printf(" RPcnt=%d", bp[0]);
956                        if (bp + 1 >= ep) {
957                                (void)printf("...)");
958                                goto bs_done;
959                        }
960                        (void)printf(" FRPcnt=%d", frpcnt = bp[1]);
961                        bp += 4;
962
963                        for (j = 0; j < frpcnt && bp < ep; j++) {
964                                /* each RP info */
965                                (void)printf(" RP%d=", j);
966                                if ((advance = pimv2_addr_print(bp,
967                                                                pimv2_unicast,
968                                                                0)) < 0) {
969                                        (void)printf("...)");
970                                        goto bs_done;
971                                }
972                                bp += advance;
973
974                                if (bp + 1 >= ep) {
975                                        (void)printf("...)");
976                                        goto bs_done;
977                                }
978                                (void)printf(",holdtime=");
979                                relts_print(EXTRACT_16BITS(bp));
980                                if (bp + 2 >= ep) {
981                                        (void)printf("...)");
982                                        goto bs_done;
983                                }
984                                (void)printf(",prio=%d", bp[2]);
985                                bp += 4;
986                        }
987                        (void)printf(")");
988                }
989           bs_done:
990                break;
991        }
992        case PIMV2_TYPE_ASSERT:
993                bp += 4; len -= 4;
994                if (bp >= ep)
995                        break;
996                (void)printf(" group=");
997                if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
998                        (void)printf("...");
999                        break;
1000                }
1001                bp += advance; len -= advance;
1002                if (bp >= ep)
1003                        break;
1004                (void)printf(" src=");
1005                if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
1006                        (void)printf("...");
1007                        break;
1008                }
1009                bp += advance; len -= advance;
1010                if (bp + 8 > ep)
1011                        break;
1012                if (bp[0] & 0x80)
1013                        (void)printf(" RPT");
1014                (void)printf(" pref=%u", EXTRACT_32BITS(&bp[0]) & 0x7fffffff);
1015                (void)printf(" metric=%u", EXTRACT_32BITS(&bp[4]));
1016                break;
1017
1018        case PIMV2_TYPE_CANDIDATE_RP:
1019        {
1020                int i, pfxcnt;
1021                bp += 4;
1022
1023                /* Prefix-Cnt, Priority, and Holdtime */
1024                if (bp >= ep) break;
1025                (void)printf(" prefix-cnt=%d", bp[0]);
1026                pfxcnt = bp[0];
1027                if (bp + 1 >= ep) break;
1028                (void)printf(" prio=%d", bp[1]);
1029                if (bp + 3 >= ep) break;
1030                (void)printf(" holdtime=");
1031                relts_print(EXTRACT_16BITS(&bp[2]));
1032                bp += 4;
1033
1034                /* Encoded-Unicast-RP-Address */
1035                if (bp >= ep) break;
1036                (void)printf(" RP=");
1037                if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
1038                        (void)printf("...");
1039                        break;
1040                }
1041                bp += advance;
1042
1043                /* Encoded-Group Addresses */
1044                for (i = 0; i < pfxcnt && bp < ep; i++) {
1045                        (void)printf(" Group%d=", i);
1046                        if ((advance = pimv2_addr_print(bp, pimv2_group, 0))
1047                            < 0) {
1048                                (void)printf("...");
1049                                break;
1050                        }
1051                        bp += advance;
1052                }
1053                break;
1054        }
1055
1056        case PIMV2_TYPE_PRUNE_REFRESH:
1057                (void)printf(" src=");
1058                if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
1059                        (void)printf("...");
1060                        break;
1061                }
1062                bp += advance;
1063                (void)printf(" grp=");
1064                if ((advance = pimv2_addr_print(bp, pimv2_group, 0)) < 0) {
1065                        (void)printf("...");
1066                        break;
1067                }
1068                bp += advance;
1069                (void)printf(" forwarder=");
1070                if ((advance = pimv2_addr_print(bp, pimv2_unicast, 0)) < 0) {
1071                        (void)printf("...");
1072                        break;
1073                }
1074                bp += advance;
1075                TCHECK2(bp[0], 2);
1076                (void)printf(" TUNR ");
1077                relts_print(EXTRACT_16BITS(bp));
1078                break;
1079
1080
1081         default:
1082                (void)printf(" [type %d]", PIM_TYPE(pim->pim_typever));
1083                break;
1084        }
1085
1086        return;
1087
1088trunc:
1089        (void)printf("[|pim]");
1090}
1091
1092/*
1093 * Local Variables:
1094 * c-style: whitesmith
1095 * c-basic-offset: 8
1096 * End:
1097 */
Note: See TracBrowser for help on using the repository browser.