source: rtems-libbsd/freebsd/contrib/tcpdump/print-pgm.c @ 084d4db

4.11
Last change on this file since 084d4db 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: 19.8 KB
Line 
1#include <machine/rtems-bsd-user-space.h>
2
3/*
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that: (1) source code
6 * distributions retain the above copyright notice and this paragraph
7 * in its entirety, and (2) distributions including binary code include
8 * the above copyright notice and this paragraph in its entirety in
9 * the documentation or other materials provided with the distribution.
10 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
11 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
12 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
13 * FOR A PARTICULAR PURPOSE.
14 *
15 * Original code by Andy Heffernan (ahh@juniper.net)
16 */
17
18#ifndef lint
19static const char rcsid[] _U_ =
20    "@(#) $Header: /tcpdump/master/tcpdump/print-pgm.c,v 1.5 2005-06-07 22:05:58 guy Exp $";
21#endif
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <tcpdump-stdinc.h>
28
29#include <stdio.h>
30#include <stdlib.h>
31#include <string.h>
32
33#include "interface.h"
34#include "extract.h"
35#include "addrtoname.h"
36
37#include "ip.h"
38#ifdef INET6
39#include "ip6.h"
40#endif
41#include "ipproto.h"
42
43/*
44 * PGM header (RFC 3208)
45 */
46struct pgm_header {
47    u_int16_t   pgm_sport;
48    u_int16_t   pgm_dport;
49    u_int8_t    pgm_type;
50    u_int8_t    pgm_options;
51    u_int16_t   pgm_sum;
52    u_int8_t    pgm_gsid[6];
53    u_int16_t   pgm_length;
54};
55
56struct pgm_spm {
57    u_int32_t   pgms_seq;
58    u_int32_t   pgms_trailseq;
59    u_int32_t   pgms_leadseq;
60    u_int16_t   pgms_nla_afi;
61    u_int16_t   pgms_reserved;
62    /* ... u_int8_t     pgms_nla[0]; */
63    /* ... options */
64};
65
66struct pgm_nak {
67    u_int32_t   pgmn_seq;
68    u_int16_t   pgmn_source_afi;
69    u_int16_t   pgmn_reserved;
70    /* ... u_int8_t     pgmn_source[0]; */
71    /* ... u_int16_t    pgmn_group_afi */
72    /* ... u_int16_t    pgmn_reserved2; */
73    /* ... u_int8_t     pgmn_group[0]; */
74    /* ... options */
75};
76
77struct pgm_ack {
78    u_int32_t   pgma_rx_max_seq;
79    u_int32_t   pgma_bitmap;
80    /* ... options */
81};
82
83struct pgm_poll {
84    u_int32_t   pgmp_seq;
85    u_int16_t   pgmp_round;
86    u_int16_t   pgmp_reserved;
87    /* ... options */
88};
89
90struct pgm_polr {
91    u_int32_t   pgmp_seq;
92    u_int16_t   pgmp_round;
93    u_int16_t   pgmp_subtype;
94    u_int16_t   pgmp_nla_afi;
95    u_int16_t   pgmp_reserved;
96    /* ... u_int8_t     pgmp_nla[0]; */
97    /* ... options */
98};
99
100struct pgm_data {
101    u_int32_t   pgmd_seq;
102    u_int32_t   pgmd_trailseq;
103    /* ... options */
104};
105
106typedef enum _pgm_type {
107    PGM_SPM = 0,                /* source path message */
108    PGM_POLL = 1,               /* POLL Request */
109    PGM_POLR = 2,               /* POLL Response */
110    PGM_ODATA = 4,              /* original data */
111    PGM_RDATA = 5,              /* repair data */
112    PGM_NAK = 8,                /* NAK */
113    PGM_NULLNAK = 9,            /* Null NAK */
114    PGM_NCF = 10,               /* NAK Confirmation */
115    PGM_ACK = 11,               /* ACK for congestion control */
116    PGM_SPMR = 12,              /* SPM request */
117    PGM_MAX = 255
118} pgm_type;
119
120#define PGM_OPT_BIT_PRESENT     0x01
121#define PGM_OPT_BIT_NETWORK     0x02
122#define PGM_OPT_BIT_VAR_PKTLEN  0x40
123#define PGM_OPT_BIT_PARITY      0x80
124
125#define PGM_OPT_LENGTH          0x00
126#define PGM_OPT_FRAGMENT        0x01
127#define PGM_OPT_NAK_LIST        0x02
128#define PGM_OPT_JOIN            0x03
129#define PGM_OPT_NAK_BO_IVL      0x04
130#define PGM_OPT_NAK_BO_RNG      0x05
131
132#define PGM_OPT_REDIRECT        0x07
133#define PGM_OPT_PARITY_PRM      0x08
134#define PGM_OPT_PARITY_GRP      0x09
135#define PGM_OPT_CURR_TGSIZE     0x0A
136#define PGM_OPT_NBR_UNREACH     0x0B
137#define PGM_OPT_PATH_NLA        0x0C
138
139#define PGM_OPT_SYN             0x0D
140#define PGM_OPT_FIN             0x0E
141#define PGM_OPT_RST             0x0F
142#define PGM_OPT_CR              0x10
143#define PGM_OPT_CRQST           0x11
144
145#define PGM_OPT_PGMCC_DATA      0x12
146#define PGM_OPT_PGMCC_FEEDBACK  0x13
147     
148#define PGM_OPT_MASK            0x7f
149
150#define PGM_OPT_END             0x80    /* end of options marker */
151
152#define PGM_MIN_OPT_LEN         4
153
154#ifndef AFI_IP
155#define AFI_IP          1
156#define AFI_IP6         2
157#endif
158
159void
160pgm_print(register const u_char *bp, register u_int length,
161          register const u_char *bp2)
162{
163        register const struct pgm_header *pgm;
164        register const struct ip *ip;
165        register char ch;
166        u_int16_t sport, dport;
167        int addr_size;
168        const void *nla;
169        int nla_af;
170#ifdef INET6
171        char nla_buf[INET6_ADDRSTRLEN];
172        register const struct ip6_hdr *ip6;
173#else
174        char nla_buf[INET_ADDRSTRLEN];
175#endif
176        u_int8_t opt_type, opt_len, flags1, flags2;
177        u_int32_t seq, opts_len, len, offset;
178
179        pgm = (struct pgm_header *)bp;
180        ip = (struct ip *)bp2;
181#ifdef INET6
182        if (IP_V(ip) == 6)
183                ip6 = (struct ip6_hdr *)bp2;
184        else
185                ip6 = NULL;
186#else /* INET6 */
187        if (IP_V(ip) == 6) {
188                (void)printf("Can't handle IPv6");
189                return;
190        }
191#endif /* INET6 */
192        ch = '\0';
193        if (!TTEST(pgm->pgm_dport)) {
194#ifdef INET6
195                if (ip6) {
196                        (void)printf("%s > %s: [|pgm]",
197                                ip6addr_string(&ip6->ip6_src),
198                                ip6addr_string(&ip6->ip6_dst));
199                        return;
200                } else
201#endif /* INET6 */
202                {
203                        (void)printf("%s > %s: [|pgm]",
204                                ipaddr_string(&ip->ip_src),
205                                ipaddr_string(&ip->ip_dst));
206                        return;
207                }
208        }
209
210        sport = EXTRACT_16BITS(&pgm->pgm_sport);
211        dport = EXTRACT_16BITS(&pgm->pgm_dport);
212
213#ifdef INET6
214        if (ip6) {
215                if (ip6->ip6_nxt == IPPROTO_PGM) {
216                        (void)printf("%s.%s > %s.%s: ",
217                                ip6addr_string(&ip6->ip6_src),
218                                tcpport_string(sport),
219                                ip6addr_string(&ip6->ip6_dst),
220                                tcpport_string(dport));
221                } else {
222                        (void)printf("%s > %s: ",
223                                tcpport_string(sport), tcpport_string(dport));
224                }
225        } else
226#endif /*INET6*/
227        {
228                if (ip->ip_p == IPPROTO_PGM) {
229                        (void)printf("%s.%s > %s.%s: ",
230                                ipaddr_string(&ip->ip_src),
231                                tcpport_string(sport),
232                                ipaddr_string(&ip->ip_dst),
233                                tcpport_string(dport));
234                } else {
235                        (void)printf("%s > %s: ",
236                                tcpport_string(sport), tcpport_string(dport));
237                }
238        }
239
240        TCHECK(*pgm);
241
242        (void)printf("PGM, length %u", pgm->pgm_length);
243
244        if (!vflag)
245            return;
246
247        if (length > pgm->pgm_length)
248            length = pgm->pgm_length;
249
250        (void)printf(" 0x%02x%02x%02x%02x%02x%02x ",
251                     pgm->pgm_gsid[0],
252                     pgm->pgm_gsid[1],
253                     pgm->pgm_gsid[2],
254                     pgm->pgm_gsid[3],
255                     pgm->pgm_gsid[4],
256                     pgm->pgm_gsid[5]);
257        switch (pgm->pgm_type) {
258        case PGM_SPM: {
259            struct pgm_spm *spm;
260
261            spm = (struct pgm_spm *)(pgm + 1);
262            TCHECK(*spm);
263
264            switch (EXTRACT_16BITS(&spm->pgms_nla_afi)) {
265            case AFI_IP:
266                addr_size = sizeof(struct in_addr);
267                nla_af = AF_INET;
268                break;
269#ifdef INET6
270            case AFI_IP6:
271                addr_size = sizeof(struct in6_addr);
272                nla_af = AF_INET6;
273                break;
274#endif
275            default:
276                goto trunc;
277                break;
278            }
279            bp = (u_char *) (spm + 1);
280            TCHECK2(*bp, addr_size);
281            nla = bp;
282            bp += addr_size;
283
284            inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
285            (void)printf("SPM seq %u trail %u lead %u nla %s",
286                         EXTRACT_32BITS(&spm->pgms_seq),
287                         EXTRACT_32BITS(&spm->pgms_trailseq),
288                         EXTRACT_32BITS(&spm->pgms_leadseq),
289                         nla_buf);
290            break;
291        }
292
293        case PGM_POLL: {
294            struct pgm_poll *poll;
295
296            poll = (struct pgm_poll *)(pgm + 1);
297            TCHECK(*poll);
298            (void)printf("POLL seq %u round %u",
299                         EXTRACT_32BITS(&poll->pgmp_seq),
300                         EXTRACT_16BITS(&poll->pgmp_round));
301            bp = (u_char *) (poll + 1);
302            break;
303        }
304        case PGM_POLR: {
305            struct pgm_polr *polr;
306            u_int32_t ivl, rnd, mask;
307
308            polr = (struct pgm_polr *)(pgm + 1);
309            TCHECK(*polr);
310
311            switch (EXTRACT_16BITS(&polr->pgmp_nla_afi)) {
312            case AFI_IP:
313                addr_size = sizeof(struct in_addr);
314                nla_af = AF_INET;
315                break;
316#ifdef INET6
317            case AFI_IP6:
318                addr_size = sizeof(struct in6_addr);
319                nla_af = AF_INET6;
320                break;
321#endif
322            default:
323                goto trunc;
324                break;
325            }
326            bp = (u_char *) (polr + 1);
327            TCHECK2(*bp, addr_size);
328            nla = bp;
329            bp += addr_size;
330
331            inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
332
333            TCHECK2(*bp, sizeof(u_int32_t));
334            ivl = EXTRACT_32BITS(bp);
335            bp += sizeof(u_int32_t);
336
337            TCHECK2(*bp, sizeof(u_int32_t));
338            rnd = EXTRACT_32BITS(bp);
339            bp += sizeof(u_int32_t);
340
341            TCHECK2(*bp, sizeof(u_int32_t));
342            mask = EXTRACT_32BITS(bp);
343            bp += sizeof(u_int32_t);
344
345            (void)printf("POLR seq %u round %u nla %s ivl %u rnd 0x%08x "
346                         "mask 0x%08x", EXTRACT_32BITS(&polr->pgmp_seq),
347                         EXTRACT_16BITS(&polr->pgmp_round), nla_buf, ivl, rnd, mask);
348            break;
349        }
350        case PGM_ODATA: {
351            struct pgm_data *odata;
352
353            odata = (struct pgm_data *)(pgm + 1);
354            TCHECK(*odata);
355            (void)printf("ODATA trail %u seq %u",
356                         EXTRACT_32BITS(&odata->pgmd_trailseq),
357                         EXTRACT_32BITS(&odata->pgmd_seq));
358            bp = (u_char *) (odata + 1);
359            break;
360        }
361
362        case PGM_RDATA: {
363            struct pgm_data *rdata;
364
365            rdata = (struct pgm_data *)(pgm + 1);
366            TCHECK(*rdata);
367            (void)printf("RDATA trail %u seq %u",
368                         EXTRACT_32BITS(&rdata->pgmd_trailseq),
369                         EXTRACT_32BITS(&rdata->pgmd_seq));
370            bp = (u_char *) (rdata + 1);
371            break;
372        }
373
374        case PGM_NAK:
375        case PGM_NULLNAK:
376        case PGM_NCF: {
377            struct pgm_nak *nak;
378            const void *source, *group;
379            int source_af, group_af;
380#ifdef INET6
381            char source_buf[INET6_ADDRSTRLEN], group_buf[INET6_ADDRSTRLEN];
382#else
383            char source_buf[INET_ADDRSTRLEN], group_buf[INET_ADDRSTRLEN];
384#endif
385
386            nak = (struct pgm_nak *)(pgm + 1);
387            TCHECK(*nak);
388
389            /*
390             * Skip past the source, saving info along the way
391             * and stopping if we don't have enough.
392             */
393            switch (EXTRACT_16BITS(&nak->pgmn_source_afi)) {
394            case AFI_IP:
395                addr_size = sizeof(struct in_addr);
396                source_af = AF_INET;
397                break;
398#ifdef INET6
399            case AFI_IP6:
400                addr_size = sizeof(struct in6_addr);
401                source_af = AF_INET6;
402                break;
403#endif
404            default:
405                goto trunc;
406                break;
407            }
408            bp = (u_char *) (nak + 1);
409            TCHECK2(*bp, addr_size);
410            source = bp;
411            bp += addr_size;
412
413            /*
414             * Skip past the group, saving info along the way
415             * and stopping if we don't have enough.
416             */
417            switch (EXTRACT_16BITS(bp)) {
418            case AFI_IP:
419                addr_size = sizeof(struct in_addr);
420                group_af = AF_INET;
421                break;
422#ifdef INET6
423            case AFI_IP6:
424                addr_size = sizeof(struct in6_addr);
425                group_af = AF_INET6;
426                break;
427#endif
428            default:
429                goto trunc;
430                break;
431            }
432            bp += (2 * sizeof(u_int16_t));
433            TCHECK2(*bp, addr_size);
434            group = bp;
435            bp += addr_size;
436
437            /*
438             * Options decoding can go here.
439             */
440            inet_ntop(source_af, source, source_buf, sizeof(source_buf));
441            inet_ntop(group_af, group, group_buf, sizeof(group_buf));
442            switch (pgm->pgm_type) {
443                case PGM_NAK:
444                    (void)printf("NAK ");
445                    break;
446                case PGM_NULLNAK:
447                    (void)printf("NNAK ");
448                    break;
449                case PGM_NCF:
450                    (void)printf("NCF ");
451                    break;
452                default:
453                    break;
454            }
455            (void)printf("(%s -> %s), seq %u",
456                         source_buf, group_buf, EXTRACT_32BITS(&nak->pgmn_seq));
457            break;
458        }
459
460        case PGM_ACK: {
461            struct pgm_ack *ack;
462
463            ack = (struct pgm_ack *)(pgm + 1);
464            TCHECK(*ack);
465            (void)printf("ACK seq %u",
466                         EXTRACT_32BITS(&ack->pgma_rx_max_seq));
467            bp = (u_char *) (ack + 1);
468            break;
469        }
470
471        case PGM_SPMR:
472            (void)printf("SPMR");
473            break;
474
475        default:
476            (void)printf("UNKNOWN type %0x02x", pgm->pgm_type);
477            break;
478
479        }
480        if (pgm->pgm_options & PGM_OPT_BIT_PRESENT) {     
481
482            /*
483             * make sure there's enough for the first option header
484             */
485            if (!TTEST2(*bp, PGM_MIN_OPT_LEN)) {
486                (void)printf("[|OPT]");
487                return;
488            }
489
490            /*
491             * That option header MUST be an OPT_LENGTH option
492             * (see the first paragraph of section 9.1 in RFC 3208).
493             */
494            opt_type = *bp++;
495            if ((opt_type & PGM_OPT_MASK) != PGM_OPT_LENGTH) {
496                (void)printf("[First option bad, should be PGM_OPT_LENGTH, is %u]", opt_type & PGM_OPT_MASK);
497                return;
498            }
499            opt_len = *bp++;
500            if (opt_len != 4) {
501                (void)printf("[Bad OPT_LENGTH option, length %u != 4]", opt_len);
502                return;
503            }
504            opts_len = EXTRACT_16BITS(bp);
505            if (opts_len < 4) {
506                (void)printf("[Bad total option length %u < 4]", opts_len);
507                return;
508            }
509            bp += sizeof(u_int16_t);
510            (void)printf(" OPTS LEN %d", opts_len);
511            opts_len -= 4;
512
513            while (opts_len) {
514                if (opts_len < PGM_MIN_OPT_LEN) {
515                    (void)printf("[Total option length leaves no room for final option]");
516                    return;
517                }
518                opt_type = *bp++;
519                opt_len = *bp++;
520                if (opt_len < PGM_MIN_OPT_LEN) {
521                    (void)printf("[Bad option, length %u < %u]", opt_len,
522                        PGM_MIN_OPT_LEN);
523                    break;
524                }
525                if (opts_len < opt_len) {
526                    (void)printf("[Total option length leaves no room for final option]");
527                    return;
528                }
529                if (!TTEST2(*bp, opt_len - 2)) {
530                    (void)printf(" [|OPT]");
531                    return;
532                }
533
534                switch (opt_type & PGM_OPT_MASK) {
535                case PGM_OPT_LENGTH:
536                    if (opt_len != 4) {
537                        (void)printf("[Bad OPT_LENGTH option, length %u != 4]", opt_len);
538                        return;
539                    }
540                    (void)printf(" OPTS LEN (extra?) %d", EXTRACT_16BITS(bp));
541                    bp += sizeof(u_int16_t);
542                    opts_len -= 4;
543                    break;
544
545                case PGM_OPT_FRAGMENT:
546                    if (opt_len != 16) {
547                        (void)printf("[Bad OPT_FRAGMENT option, length %u != 16]", opt_len);
548                        return;
549                    }
550                    flags1 = *bp++;
551                    flags2 = *bp++;
552                    seq = EXTRACT_32BITS(bp);
553                    bp += sizeof(u_int32_t);
554                    offset = EXTRACT_32BITS(bp);
555                    bp += sizeof(u_int32_t);
556                    len = EXTRACT_32BITS(bp);
557                    bp += sizeof(u_int32_t);
558                    (void)printf(" FRAG seq %u off %u len %u", seq, offset, len);
559                    opts_len -= 16;
560                    break;
561
562                case PGM_OPT_NAK_LIST:
563                    flags1 = *bp++;
564                    flags2 = *bp++;
565                    opt_len -= sizeof(u_int32_t);       /* option header */
566                    (void)printf(" NAK LIST");
567                    while (opt_len) {
568                        if (opt_len < sizeof(u_int32_t)) {
569                            (void)printf("[Option length not a multiple of 4]");
570                            return;
571                        }
572                        TCHECK2(*bp, sizeof(u_int32_t));
573                        (void)printf(" %u", EXTRACT_32BITS(bp));
574                        bp += sizeof(u_int32_t);
575                        opt_len -= sizeof(u_int32_t);
576                        opts_len -= sizeof(u_int32_t);
577                    }
578                    break;
579
580                case PGM_OPT_JOIN:
581                    if (opt_len != 8) {
582                        (void)printf("[Bad OPT_JOIN option, length %u != 8]", opt_len);
583                        return;
584                    }
585                    flags1 = *bp++;
586                    flags2 = *bp++;
587                    seq = EXTRACT_32BITS(bp);
588                    bp += sizeof(u_int32_t);
589                    (void)printf(" JOIN %u", seq);
590                    opts_len -= 8;
591                    break;
592
593                case PGM_OPT_NAK_BO_IVL:
594                    if (opt_len != 12) {
595                        (void)printf("[Bad OPT_NAK_BO_IVL option, length %u != 12]", opt_len);
596                        return;
597                    }
598                    flags1 = *bp++;
599                    flags2 = *bp++;
600                    offset = EXTRACT_32BITS(bp);
601                    bp += sizeof(u_int32_t);
602                    seq = EXTRACT_32BITS(bp);
603                    bp += sizeof(u_int32_t);
604                    (void)printf(" BACKOFF ivl %u ivlseq %u", offset, seq);
605                    opts_len -= 12;
606                    break;
607
608                case PGM_OPT_NAK_BO_RNG:
609                    if (opt_len != 12) {
610                        (void)printf("[Bad OPT_NAK_BO_RNG option, length %u != 12]", opt_len);
611                        return;
612                    }
613                    flags1 = *bp++;
614                    flags2 = *bp++;
615                    offset = EXTRACT_32BITS(bp);
616                    bp += sizeof(u_int32_t);
617                    seq = EXTRACT_32BITS(bp);
618                    bp += sizeof(u_int32_t);
619                    (void)printf(" BACKOFF max %u min %u", offset, seq);
620                    opts_len -= 12;
621                    break;
622
623                case PGM_OPT_REDIRECT:
624                    flags1 = *bp++;
625                    flags2 = *bp++;
626                    switch (EXTRACT_16BITS(bp)) {
627                    case AFI_IP:
628                        addr_size = sizeof(struct in_addr);
629                        nla_af = AF_INET;
630                        break;
631#ifdef INET6
632                    case AFI_IP6:
633                        addr_size = sizeof(struct in6_addr);
634                        nla_af = AF_INET6;
635                        break;
636#endif
637                    default:
638                        goto trunc;
639                        break;
640                    }
641                    bp += (2 * sizeof(u_int16_t));
642                    if (opt_len != 4 + addr_size) {
643                        (void)printf("[Bad OPT_REDIRECT option, length %u != 4 + address size]", opt_len);
644                        return;
645                    }
646                    TCHECK2(*bp, addr_size);
647                    nla = bp;
648                    bp += addr_size;
649
650                    inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
651                    (void)printf(" REDIRECT %s",  (char *)nla);
652                    opts_len -= 4 + addr_size;
653                    break;
654
655                case PGM_OPT_PARITY_PRM:
656                    if (opt_len != 8) {
657                        (void)printf("[Bad OPT_PARITY_PRM option, length %u != 8]", opt_len);
658                        return;
659                    }
660                    flags1 = *bp++;
661                    flags2 = *bp++;
662                    len = EXTRACT_32BITS(bp);
663                    bp += sizeof(u_int32_t);
664                    (void)printf(" PARITY MAXTGS %u", len);
665                    opts_len -= 8;
666                    break;
667
668                case PGM_OPT_PARITY_GRP:
669                    if (opt_len != 8) {
670                        (void)printf("[Bad OPT_PARITY_GRP option, length %u != 8]", opt_len);
671                        return;
672                    }
673                    flags1 = *bp++;
674                    flags2 = *bp++;
675                    seq = EXTRACT_32BITS(bp);
676                    bp += sizeof(u_int32_t);
677                    (void)printf(" PARITY GROUP %u", seq);
678                    opts_len -= 8;
679                    break;
680
681                case PGM_OPT_CURR_TGSIZE:
682                    if (opt_len != 8) {
683                        (void)printf("[Bad OPT_CURR_TGSIZE option, length %u != 8]", opt_len);
684                        return;
685                    }
686                    flags1 = *bp++;
687                    flags2 = *bp++;
688                    len = EXTRACT_32BITS(bp);
689                    bp += sizeof(u_int32_t);
690                    (void)printf(" PARITY ATGS %u", len);
691                    opts_len -= 8;
692                    break;
693
694                case PGM_OPT_NBR_UNREACH:
695                    if (opt_len != 4) {
696                        (void)printf("[Bad OPT_NBR_UNREACH option, length %u != 4]", opt_len);
697                        return;
698                    }
699                    flags1 = *bp++;
700                    flags2 = *bp++;
701                    (void)printf(" NBR_UNREACH");
702                    opts_len -= 4;
703                    break;
704
705                case PGM_OPT_PATH_NLA:
706                    (void)printf(" PATH_NLA [%d]", opt_len);
707                    bp += opt_len;
708                    opts_len -= opt_len;
709                    break;
710
711                case PGM_OPT_SYN:
712                    if (opt_len != 4) {
713                        (void)printf("[Bad OPT_SYN option, length %u != 4]", opt_len);
714                        return;
715                    }
716                    flags1 = *bp++;
717                    flags2 = *bp++;
718                    (void)printf(" SYN");
719                    opts_len -= 4;
720                    break;
721
722                case PGM_OPT_FIN:
723                    if (opt_len != 4) {
724                        (void)printf("[Bad OPT_FIN option, length %u != 4]", opt_len);
725                        return;
726                    }
727                    flags1 = *bp++;
728                    flags2 = *bp++;
729                    (void)printf(" FIN");
730                    opts_len -= 4;
731                    break;
732
733                case PGM_OPT_RST:
734                    if (opt_len != 4) {
735                        (void)printf("[Bad OPT_RST option, length %u != 4]", opt_len);
736                        return;
737                    }
738                    flags1 = *bp++;
739                    flags2 = *bp++;
740                    (void)printf(" RST");
741                    opts_len -= 4;
742                    break;
743
744                case PGM_OPT_CR:
745                    (void)printf(" CR");
746                    bp += opt_len;
747                    opts_len -= opt_len;
748                    break;
749
750                case PGM_OPT_CRQST:
751                    if (opt_len != 4) {
752                        (void)printf("[Bad OPT_CRQST option, length %u != 4]", opt_len);
753                        return;
754                    }
755                    flags1 = *bp++;
756                    flags2 = *bp++;
757                    (void)printf(" CRQST");
758                    opts_len -= 4;
759                    break;
760
761                case PGM_OPT_PGMCC_DATA:
762                    flags1 = *bp++;
763                    flags2 = *bp++;
764                    offset = EXTRACT_32BITS(bp);
765                    bp += sizeof(u_int32_t);
766                    switch (EXTRACT_16BITS(bp)) {
767                    case AFI_IP:
768                        addr_size = sizeof(struct in_addr);
769                        nla_af = AF_INET;
770                        break;
771#ifdef INET6
772                    case AFI_IP6:
773                        addr_size = sizeof(struct in6_addr);
774                        nla_af = AF_INET6;
775                        break;
776#endif
777                    default:
778                        goto trunc;
779                        break;
780                    }
781                    bp += (2 * sizeof(u_int16_t));
782                    if (opt_len != 12 + addr_size) {
783                        (void)printf("[Bad OPT_PGMCC_DATA option, length %u != 12 + address size]", opt_len);
784                        return;
785                    }
786                    TCHECK2(*bp, addr_size);
787                    nla = bp;
788                    bp += addr_size;
789
790                    inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
791                    (void)printf(" PGMCC DATA %u %s", offset, (char*)nla);
792                    opts_len -= 16;
793                    break;
794
795                case PGM_OPT_PGMCC_FEEDBACK:
796                    flags1 = *bp++;
797                    flags2 = *bp++;
798                    offset = EXTRACT_32BITS(bp);
799                    bp += sizeof(u_int32_t);
800                    switch (EXTRACT_16BITS(bp)) {
801                    case AFI_IP:
802                        addr_size = sizeof(struct in_addr);
803                        nla_af = AF_INET;
804                        break;
805#ifdef INET6
806                    case AFI_IP6:
807                        addr_size = sizeof(struct in6_addr);
808                        nla_af = AF_INET6;
809                        break;
810#endif
811                    default:
812                        goto trunc;
813                        break;
814                    }
815                    bp += (2 * sizeof(u_int16_t));
816                    if (opt_len != 12 + addr_size) {
817                        (void)printf("[Bad OPT_PGMCC_FEEDBACK option, length %u != 12 + address size]", opt_len);
818                        return;
819                    }
820                    TCHECK2(*bp, addr_size);
821                    nla = bp;
822                    bp += addr_size;
823
824                    inet_ntop(nla_af, nla, nla_buf, sizeof(nla_buf));
825                    (void)printf(" PGMCC FEEDBACK %u %s", offset, (char*)nla);
826                    opts_len -= 16;
827                    break;
828
829                default:
830                    (void)printf(" OPT_%02X [%d] ", opt_type, opt_len);
831                    bp += opt_len;
832                    opts_len -= opt_len;
833                    break;
834                }
835
836                if (opt_type & PGM_OPT_END)
837                    break;
838             }
839        }
840
841        (void)printf(" [%u]", EXTRACT_16BITS(&pgm->pgm_length));
842
843        return;
844
845trunc:
846        fputs("[|pgm]", stdout);
847        if (ch != '\0')
848                putchar('>');
849}
Note: See TracBrowser for help on using the repository browser.