Home | History | Annotate | Download | only in tcpdump
      1 /*
      2  * Redistribution and use in source and binary forms, with or without
      3  * modification, are permitted provided that: (1) source code
      4  * distributions retain the above copyright notice and this paragraph
      5  * in its entirety, and (2) distributions including binary code include
      6  * the above copyright notice and this paragraph in its entirety in
      7  * the documentation or other materials provided with the distribution.
      8  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
      9  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
     10  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
     11  * FOR A PARTICULAR PURPOSE.
     12  *
     13  * Original code by Hannes Gredler (hannes (at) juniper.net)
     14  */
     15 
     16 #ifndef lint
     17 static const char rcsid[] _U_ =
     18     "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.8.2.22 2006/05/10 22:42:46 guy Exp $ (LBL)";
     19 #endif
     20 
     21 #ifdef HAVE_CONFIG_H
     22 #include "config.h"
     23 #endif
     24 
     25 #include <tcpdump-stdinc.h>
     26 
     27 #include <pcap.h>
     28 #include <stdio.h>
     29 
     30 #include "interface.h"
     31 #include "addrtoname.h"
     32 #include "extract.h"
     33 #include "ppp.h"
     34 #include "llc.h"
     35 #include "nlpid.h"
     36 #include "ethertype.h"
     37 #include "atm.h"
     38 
     39 #define JUNIPER_BPF_OUT           0       /* Outgoing packet */
     40 #define JUNIPER_BPF_IN            1       /* Incoming packet */
     41 #define JUNIPER_BPF_PKT_IN        0x1     /* Incoming packet */
     42 #define JUNIPER_BPF_NO_L2         0x2     /* L2 header stripped */
     43 #define JUNIPER_BPF_EXT           0x80    /* extensions present */
     44 #define JUNIPER_MGC_NUMBER        0x4d4743 /* = "MGC" */
     45 
     46 #define JUNIPER_LSQ_COOKIE_RE         (1 << 3)
     47 #define JUNIPER_LSQ_COOKIE_DIR        (1 << 2)
     48 #define JUNIPER_LSQ_L3_PROTO_SHIFT     4
     49 #define JUNIPER_LSQ_L3_PROTO_MASK     (0x17 << JUNIPER_LSQ_L3_PROTO_SHIFT)
     50 #define JUNIPER_LSQ_L3_PROTO_IPV4     (0 << JUNIPER_LSQ_L3_PROTO_SHIFT)
     51 #define JUNIPER_LSQ_L3_PROTO_IPV6     (1 << JUNIPER_LSQ_L3_PROTO_SHIFT)
     52 #define JUNIPER_LSQ_L3_PROTO_MPLS     (2 << JUNIPER_LSQ_L3_PROTO_SHIFT)
     53 #define JUNIPER_LSQ_L3_PROTO_ISO      (3 << JUNIPER_LSQ_L3_PROTO_SHIFT)
     54 #define AS_PIC_COOKIE_LEN 8
     55 
     56 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE 1
     57 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE 2
     58 #define JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE 3
     59 #define JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE 4
     60 #define JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE 5
     61 
     62 static struct tok juniper_ipsec_type_values[] = {
     63     { JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE, "ESP ENCR-AUTH" },
     64     { JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE, "ESP ENCR-AH AUTH" },
     65     { JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE, "ESP AUTH" },
     66     { JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE, "AH AUTH" },
     67     { JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE, "ESP ENCR" },
     68     { 0, NULL}
     69 };
     70 
     71 static struct tok juniper_direction_values[] = {
     72     { JUNIPER_BPF_IN,  "In"},
     73     { JUNIPER_BPF_OUT, "Out"},
     74     { 0, NULL}
     75 };
     76 
     77 struct juniper_cookie_table_t {
     78     u_int32_t pictype;		/* pic type */
     79     u_int8_t  cookie_len;       /* cookie len */
     80     const char *s;		/* pic name */
     81 };
     82 
     83 static struct juniper_cookie_table_t juniper_cookie_table[] = {
     84 #ifdef DLT_JUNIPER_ATM1
     85     { DLT_JUNIPER_ATM1,  4, "ATM1"},
     86 #endif
     87 #ifdef DLT_JUNIPER_ATM2
     88     { DLT_JUNIPER_ATM2,  8, "ATM2"},
     89 #endif
     90 #ifdef DLT_JUNIPER_MLPPP
     91     { DLT_JUNIPER_MLPPP, 2, "MLPPP"},
     92 #endif
     93 #ifdef DLT_JUNIPER_MLFR
     94     { DLT_JUNIPER_MLFR,  2, "MLFR"},
     95 #endif
     96 #ifdef DLT_JUNIPER_MFR
     97     { DLT_JUNIPER_MFR,   4, "MFR"},
     98 #endif
     99 #ifdef DLT_JUNIPER_PPPOE
    100     { DLT_JUNIPER_PPPOE, 0, "PPPoE"},
    101 #endif
    102 #ifdef DLT_JUNIPER_PPPOE_ATM
    103     { DLT_JUNIPER_PPPOE_ATM, 0, "PPPoE ATM"},
    104 #endif
    105 #ifdef DLT_JUNIPER_GGSN
    106     { DLT_JUNIPER_GGSN, 8, "GGSN"},
    107 #endif
    108 #ifdef DLT_JUNIPER_MONITOR
    109     { DLT_JUNIPER_MONITOR, 8, "MONITOR"},
    110 #endif
    111 #ifdef DLT_JUNIPER_SERVICES
    112     { DLT_JUNIPER_SERVICES, 8, "AS"},
    113 #endif
    114 #ifdef DLT_JUNIPER_ES
    115     { DLT_JUNIPER_ES, 0, "ES"},
    116 #endif
    117     { 0, 0, NULL }
    118 };
    119 
    120 struct juniper_l2info_t {
    121     u_int32_t length;
    122     u_int32_t caplen;
    123     u_int32_t pictype;
    124     u_int8_t direction;
    125     u_int8_t header_len;
    126     u_int8_t cookie_len;
    127     u_int8_t cookie_type;
    128     u_int8_t cookie[8];
    129     u_int8_t bundle;
    130     u_int16_t proto;
    131 };
    132 
    133 #define LS_COOKIE_ID            0x54
    134 #define AS_COOKIE_ID            0x47
    135 #define LS_MLFR_COOKIE_LEN	4
    136 #define ML_MLFR_COOKIE_LEN	2
    137 #define LS_MFR_COOKIE_LEN	6
    138 #define ATM1_COOKIE_LEN         4
    139 #define ATM2_COOKIE_LEN         8
    140 
    141 #define ATM2_PKT_TYPE_MASK  0x70
    142 #define ATM2_GAP_COUNT_MASK 0x3F
    143 
    144 #define JUNIPER_PROTO_NULL          1
    145 #define JUNIPER_PROTO_IPV4          2
    146 #define JUNIPER_PROTO_IPV6          6
    147 
    148 #define MFR_BE_MASK 0xc0
    149 
    150 static struct tok juniper_protocol_values[] = {
    151     { JUNIPER_PROTO_NULL, "Null" },
    152     { JUNIPER_PROTO_IPV4, "IPv4" },
    153     { JUNIPER_PROTO_IPV6, "IPv6" },
    154     { 0, NULL}
    155 };
    156 
    157 int ip_heuristic_guess(register const u_char *, u_int);
    158 int juniper_ppp_heuristic_guess(register const u_char *, u_int);
    159 static int juniper_parse_header (const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
    160 
    161 #ifdef DLT_JUNIPER_GGSN
    162 u_int
    163 juniper_ggsn_print(const struct pcap_pkthdr *h, register const u_char *p)
    164 {
    165         struct juniper_l2info_t l2info;
    166         struct juniper_ggsn_header {
    167             u_int8_t svc_id;
    168             u_int8_t flags_len;
    169             u_int8_t proto;
    170             u_int8_t flags;
    171             u_int8_t vlan_id[2];
    172             u_int8_t res[2];
    173         };
    174         const struct juniper_ggsn_header *gh;
    175 
    176         l2info.pictype = DLT_JUNIPER_GGSN;
    177         if(juniper_parse_header(p, h, &l2info) == 0)
    178             return l2info.header_len;
    179 
    180         p+=l2info.header_len;
    181         gh = (struct juniper_ggsn_header *)p;
    182 
    183         if (eflag)
    184             printf("proto %s (%u), vlan %u: ",
    185                    tok2str(juniper_protocol_values,"Unknown",gh->proto),
    186                    gh->proto,
    187                    EXTRACT_16BITS(&gh->vlan_id[0]));
    188 
    189         switch (gh->proto) {
    190         case JUNIPER_PROTO_IPV4:
    191             ip_print(gndo, p, l2info.length);
    192             break;
    193 #ifdef INET6
    194         case JUNIPER_PROTO_IPV6:
    195             ip6_print(p, l2info.length);
    196             break;
    197 #endif /* INET6 */
    198         default:
    199             if (!eflag)
    200                 printf("unknown GGSN proto (%u)", gh->proto);
    201         }
    202 
    203         return l2info.header_len;
    204 }
    205 #endif
    206 
    207 #ifdef DLT_JUNIPER_ES
    208 u_int
    209 juniper_es_print(const struct pcap_pkthdr *h, register const u_char *p)
    210 {
    211         struct juniper_l2info_t l2info;
    212         struct juniper_ipsec_header {
    213             u_int8_t sa_index[2];
    214             u_int8_t ttl;
    215             u_int8_t type;
    216             u_int8_t spi[4];
    217             u_int8_t src_ip[4];
    218             u_int8_t dst_ip[4];
    219         };
    220         u_int rewrite_len,es_type_bundle;
    221         const struct juniper_ipsec_header *ih;
    222 
    223         l2info.pictype = DLT_JUNIPER_ES;
    224         if(juniper_parse_header(p, h, &l2info) == 0)
    225             return l2info.header_len;
    226 
    227         p+=l2info.header_len;
    228         ih = (struct juniper_ipsec_header *)p;
    229 
    230         switch (ih->type) {
    231         case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE:
    232         case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE:
    233             rewrite_len = 0;
    234             es_type_bundle = 1;
    235             break;
    236         case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE:
    237         case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE:
    238         case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE:
    239             rewrite_len = 16;
    240             es_type_bundle = 0;
    241         default:
    242             printf("ES Invalid type %u, length %u",
    243                    ih->type,
    244                    l2info.length);
    245             return l2info.header_len;
    246         }
    247 
    248         l2info.length-=rewrite_len;
    249         p+=rewrite_len;
    250 
    251         if (eflag) {
    252             if (!es_type_bundle) {
    253                 printf("ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n",
    254                        EXTRACT_16BITS(&ih->sa_index),
    255                        ih->ttl,
    256                        tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
    257                        ih->type,
    258                        EXTRACT_32BITS(&ih->spi),
    259                        ipaddr_string(EXTRACT_32BITS(&ih->src_ip)),
    260                        ipaddr_string(EXTRACT_32BITS(&ih->dst_ip)),
    261                        l2info.length);
    262             } else {
    263                 printf("ES SA, index %u, ttl %u type %s (%u), length %u\n",
    264                        EXTRACT_16BITS(&ih->sa_index),
    265                        ih->ttl,
    266                        tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
    267                        ih->type,
    268                        l2info.length);
    269             }
    270         }
    271 
    272         ip_print(gndo, p, l2info.length);
    273         return l2info.header_len;
    274 }
    275 #endif
    276 
    277 #ifdef DLT_JUNIPER_MONITOR
    278 u_int
    279 juniper_monitor_print(const struct pcap_pkthdr *h, register const u_char *p)
    280 {
    281         struct juniper_l2info_t l2info;
    282         struct juniper_monitor_header {
    283             u_int8_t pkt_type;
    284             u_int8_t padding;
    285             u_int8_t iif[2];
    286             u_int8_t service_id[4];
    287         };
    288         const struct juniper_monitor_header *mh;
    289 
    290         l2info.pictype = DLT_JUNIPER_MONITOR;
    291         if(juniper_parse_header(p, h, &l2info) == 0)
    292             return l2info.header_len;
    293 
    294         p+=l2info.header_len;
    295         mh = (struct juniper_monitor_header *)p;
    296 
    297         if (eflag)
    298             printf("service-id %u, iif %u, pkt-type %u: ",
    299                    EXTRACT_32BITS(&mh->service_id),
    300                    EXTRACT_16BITS(&mh->iif),
    301                    mh->pkt_type);
    302 
    303         /* no proto field - lets guess by first byte of IP header*/
    304         ip_heuristic_guess(p, l2info.length);
    305 
    306         return l2info.header_len;
    307 }
    308 #endif
    309 
    310 #ifdef DLT_JUNIPER_SERVICES
    311 u_int
    312 juniper_services_print(const struct pcap_pkthdr *h, register const u_char *p)
    313 {
    314         struct juniper_l2info_t l2info;
    315         struct juniper_services_header {
    316             u_int8_t svc_id;
    317             u_int8_t flags_len;
    318             u_int8_t svc_set_id[2];
    319             u_int8_t dir_iif[4];
    320         };
    321         const struct juniper_services_header *sh;
    322 
    323         l2info.pictype = DLT_JUNIPER_SERVICES;
    324         if(juniper_parse_header(p, h, &l2info) == 0)
    325             return l2info.header_len;
    326 
    327         p+=l2info.header_len;
    328         sh = (struct juniper_services_header *)p;
    329 
    330         if (eflag)
    331             printf("service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ",
    332                    sh->svc_id,
    333                    sh->flags_len,
    334                    EXTRACT_16BITS(&sh->svc_set_id),
    335                    EXTRACT_24BITS(&sh->dir_iif[1]));
    336 
    337         /* no proto field - lets guess by first byte of IP header*/
    338         ip_heuristic_guess(p, l2info.length);
    339 
    340         return l2info.header_len;
    341 }
    342 #endif
    343 
    344 #ifdef DLT_JUNIPER_PPPOE
    345 u_int
    346 juniper_pppoe_print(const struct pcap_pkthdr *h, register const u_char *p)
    347 {
    348         struct juniper_l2info_t l2info;
    349 
    350         l2info.pictype = DLT_JUNIPER_PPPOE;
    351         if(juniper_parse_header(p, h, &l2info) == 0)
    352             return l2info.header_len;
    353 
    354         p+=l2info.header_len;
    355         /* this DLT contains nothing but raw ethernet frames */
    356         ether_print(p, l2info.length, l2info.caplen);
    357         return l2info.header_len;
    358 }
    359 #endif
    360 
    361 #ifdef DLT_JUNIPER_ETHER
    362 u_int
    363 juniper_ether_print(const struct pcap_pkthdr *h, register const u_char *p)
    364 {
    365         struct juniper_l2info_t l2info;
    366 
    367         l2info.pictype = DLT_JUNIPER_ETHER;
    368         if(juniper_parse_header(p, h, &l2info) == 0)
    369             return l2info.header_len;
    370 
    371         p+=l2info.header_len;
    372         /* this DLT contains nothing but raw Ethernet frames */
    373         ether_print(p, l2info.length, l2info.caplen);
    374         return l2info.header_len;
    375 }
    376 #endif
    377 
    378 #ifdef DLT_JUNIPER_PPP
    379 u_int
    380 juniper_ppp_print(const struct pcap_pkthdr *h, register const u_char *p)
    381 {
    382         struct juniper_l2info_t l2info;
    383 
    384         l2info.pictype = DLT_JUNIPER_PPP;
    385         if(juniper_parse_header(p, h, &l2info) == 0)
    386             return l2info.header_len;
    387 
    388         p+=l2info.header_len;
    389         /* this DLT contains nothing but raw ppp frames */
    390         ppp_print(p, l2info.length);
    391         return l2info.header_len;
    392 }
    393 #endif
    394 
    395 #ifdef DLT_JUNIPER_FRELAY
    396 u_int
    397 juniper_frelay_print(const struct pcap_pkthdr *h, register const u_char *p)
    398 {
    399         struct juniper_l2info_t l2info;
    400 
    401         l2info.pictype = DLT_JUNIPER_FRELAY;
    402         if(juniper_parse_header(p, h, &l2info) == 0)
    403             return l2info.header_len;
    404 
    405         p+=l2info.header_len;
    406         /* this DLT contains nothing but raw frame-relay frames */
    407         fr_print(p, l2info.length);
    408         return l2info.header_len;
    409 }
    410 #endif
    411 
    412 #ifdef DLT_JUNIPER_CHDLC
    413 u_int
    414 juniper_chdlc_print(const struct pcap_pkthdr *h, register const u_char *p)
    415 {
    416         struct juniper_l2info_t l2info;
    417 
    418         l2info.pictype = DLT_JUNIPER_CHDLC;
    419         if(juniper_parse_header(p, h, &l2info) == 0)
    420             return l2info.header_len;
    421 
    422         p+=l2info.header_len;
    423         /* this DLT contains nothing but raw c-hdlc frames */
    424         chdlc_print(p, l2info.length);
    425         return l2info.header_len;
    426 }
    427 #endif
    428 
    429 #ifdef DLT_JUNIPER_PPPOE_ATM
    430 u_int
    431 juniper_pppoe_atm_print(const struct pcap_pkthdr *h, register const u_char *p)
    432 {
    433         struct juniper_l2info_t l2info;
    434 	u_int16_t extracted_ethertype;
    435 
    436         l2info.pictype = DLT_JUNIPER_PPPOE_ATM;
    437         if(juniper_parse_header(p, h, &l2info) == 0)
    438             return l2info.header_len;
    439 
    440         p+=l2info.header_len;
    441 
    442         extracted_ethertype = EXTRACT_16BITS(p);
    443         /* this DLT contains nothing but raw PPPoE frames,
    444          * prepended with a type field*/
    445         if (ether_encap_print(extracted_ethertype,
    446                               p+ETHERTYPE_LEN,
    447                               l2info.length-ETHERTYPE_LEN,
    448                               l2info.caplen-ETHERTYPE_LEN,
    449                               &extracted_ethertype) == 0)
    450             /* ether_type not known, probably it wasn't one */
    451             printf("unknown ethertype 0x%04x", extracted_ethertype);
    452 
    453         return l2info.header_len;
    454 }
    455 #endif
    456 
    457 #ifdef DLT_JUNIPER_MLPPP
    458 u_int
    459 juniper_mlppp_print(const struct pcap_pkthdr *h, register const u_char *p)
    460 {
    461         struct juniper_l2info_t l2info;
    462 
    463         l2info.pictype = DLT_JUNIPER_MLPPP;
    464         if(juniper_parse_header(p, h, &l2info) == 0)
    465             return l2info.header_len;
    466 
    467         /* suppress Bundle-ID if frame was captured on a child-link
    468          * best indicator if the cookie looks like a proto */
    469         if (eflag &&
    470             EXTRACT_16BITS(&l2info.cookie) != PPP_OSI &&
    471             EXTRACT_16BITS(&l2info.cookie) !=  (PPP_ADDRESS << 8 | PPP_CONTROL))
    472             printf("Bundle-ID %u: ",l2info.bundle);
    473 
    474         p+=l2info.header_len;
    475 
    476         /* first try the LSQ protos */
    477         switch(l2info.proto) {
    478         case JUNIPER_LSQ_L3_PROTO_IPV4:
    479             /* IP traffic going to the RE would not have a cookie
    480              * -> this must be incoming IS-IS over PPP
    481              */
    482             if (l2info.cookie[4] == (JUNIPER_LSQ_COOKIE_RE|JUNIPER_LSQ_COOKIE_DIR))
    483                 ppp_print(p, l2info.length);
    484             else
    485                 ip_print(gndo, p, l2info.length);
    486             return l2info.header_len;
    487 #ifdef INET6
    488         case JUNIPER_LSQ_L3_PROTO_IPV6:
    489             ip6_print(p,l2info.length);
    490             return l2info.header_len;
    491 #endif
    492         case JUNIPER_LSQ_L3_PROTO_MPLS:
    493             mpls_print(p,l2info.length);
    494             return l2info.header_len;
    495         case JUNIPER_LSQ_L3_PROTO_ISO:
    496             isoclns_print(p,l2info.length,l2info.caplen);
    497             return l2info.header_len;
    498         default:
    499             break;
    500         }
    501 
    502         /* zero length cookie ? */
    503         switch (EXTRACT_16BITS(&l2info.cookie)) {
    504         case PPP_OSI:
    505             ppp_print(p-2,l2info.length+2);
    506             break;
    507         case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */
    508         default:
    509             ppp_print(p,l2info.length);
    510             break;
    511         }
    512 
    513         return l2info.header_len;
    514 }
    515 #endif
    516 
    517 
    518 #ifdef DLT_JUNIPER_MFR
    519 u_int
    520 juniper_mfr_print(const struct pcap_pkthdr *h, register const u_char *p)
    521 {
    522         struct juniper_l2info_t l2info;
    523 
    524         l2info.pictype = DLT_JUNIPER_MFR;
    525         if(juniper_parse_header(p, h, &l2info) == 0)
    526             return l2info.header_len;
    527 
    528         p+=l2info.header_len;
    529 
    530         /* child-link ? */
    531         if (l2info.cookie_len == 0) {
    532             mfr_print(p,l2info.length);
    533             return l2info.header_len;
    534         }
    535 
    536         /* first try the LSQ protos */
    537         if (l2info.cookie_len == AS_PIC_COOKIE_LEN) {
    538             switch(l2info.proto) {
    539             case JUNIPER_LSQ_L3_PROTO_IPV4:
    540                 ip_print(gndo, p, l2info.length);
    541                 return l2info.header_len;
    542 #ifdef INET6
    543             case JUNIPER_LSQ_L3_PROTO_IPV6:
    544                 ip6_print(p,l2info.length);
    545                 return l2info.header_len;
    546 #endif
    547             case JUNIPER_LSQ_L3_PROTO_MPLS:
    548                 mpls_print(p,l2info.length);
    549                 return l2info.header_len;
    550             case JUNIPER_LSQ_L3_PROTO_ISO:
    551                 isoclns_print(p,l2info.length,l2info.caplen);
    552                 return l2info.header_len;
    553             default:
    554                 break;
    555             }
    556             return l2info.header_len;
    557         }
    558 
    559         /* suppress Bundle-ID if frame was captured on a child-link */
    560         if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
    561         switch (l2info.proto) {
    562         case (LLCSAP_ISONS<<8 | LLCSAP_ISONS):
    563             isoclns_print(p+1, l2info.length-1, l2info.caplen-1);
    564             break;
    565         case (LLC_UI<<8 | NLPID_Q933):
    566         case (LLC_UI<<8 | NLPID_IP):
    567         case (LLC_UI<<8 | NLPID_IP6):
    568             /* pass IP{4,6} to the OSI layer for proper link-layer printing */
    569             isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
    570             break;
    571         default:
    572             printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
    573         }
    574 
    575         return l2info.header_len;
    576 }
    577 #endif
    578 
    579 #ifdef DLT_JUNIPER_MLFR
    580 u_int
    581 juniper_mlfr_print(const struct pcap_pkthdr *h, register const u_char *p)
    582 {
    583         struct juniper_l2info_t l2info;
    584 
    585         l2info.pictype = DLT_JUNIPER_MLFR;
    586         if(juniper_parse_header(p, h, &l2info) == 0)
    587             return l2info.header_len;
    588 
    589         p+=l2info.header_len;
    590 
    591         /* suppress Bundle-ID if frame was captured on a child-link */
    592         if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
    593         switch (l2info.proto) {
    594         case (LLC_UI):
    595         case (LLC_UI<<8):
    596             isoclns_print(p, l2info.length, l2info.caplen);
    597             break;
    598         case (LLC_UI<<8 | NLPID_Q933):
    599         case (LLC_UI<<8 | NLPID_IP):
    600         case (LLC_UI<<8 | NLPID_IP6):
    601             /* pass IP{4,6} to the OSI layer for proper link-layer printing */
    602             isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
    603             break;
    604         default:
    605             printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
    606         }
    607 
    608         return l2info.header_len;
    609 }
    610 #endif
    611 
    612 /*
    613  *     ATM1 PIC cookie format
    614  *
    615  *     +-----+-------------------------+-------------------------------+
    616  *     |fmtid|     vc index            |  channel  ID                  |
    617  *     +-----+-------------------------+-------------------------------+
    618  */
    619 
    620 #ifdef DLT_JUNIPER_ATM1
    621 u_int
    622 juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p)
    623 {
    624         u_int16_t extracted_ethertype;
    625 
    626         struct juniper_l2info_t l2info;
    627 
    628         l2info.pictype = DLT_JUNIPER_ATM1;
    629         if(juniper_parse_header(p, h, &l2info) == 0)
    630             return l2info.header_len;
    631 
    632         p+=l2info.header_len;
    633 
    634         if (l2info.cookie[0] == 0x80) { /* OAM cell ? */
    635             oam_print(p,l2info.length,ATM_OAM_NOHEC);
    636             return l2info.header_len;
    637         }
    638 
    639         if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
    640             EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
    641 
    642             if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
    643                           &extracted_ethertype) != 0)
    644                 return l2info.header_len;
    645         }
    646 
    647         if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
    648             isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
    649             /* FIXME check if frame was recognized */
    650             return l2info.header_len;
    651         }
    652 
    653         if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
    654             return l2info.header_len;
    655 
    656 	return l2info.header_len;
    657 }
    658 #endif
    659 
    660 /*
    661  *     ATM2 PIC cookie format
    662  *
    663  *     +-------------------------------+---------+---+-----+-----------+
    664  *     |     channel ID                |  reserv |AAL| CCRQ| gap cnt   |
    665  *     +-------------------------------+---------+---+-----+-----------+
    666  */
    667 
    668 #ifdef DLT_JUNIPER_ATM2
    669 u_int
    670 juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p)
    671 {
    672         u_int16_t extracted_ethertype;
    673 
    674         struct juniper_l2info_t l2info;
    675 
    676         l2info.pictype = DLT_JUNIPER_ATM2;
    677         if(juniper_parse_header(p, h, &l2info) == 0)
    678             return l2info.header_len;
    679 
    680         p+=l2info.header_len;
    681 
    682         if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
    683             oam_print(p,l2info.length,ATM_OAM_NOHEC);
    684             return l2info.header_len;
    685         }
    686 
    687         if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
    688             EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
    689 
    690             if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
    691                           &extracted_ethertype) != 0)
    692                 return l2info.header_len;
    693         }
    694 
    695         if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
    696             (EXTRACT_32BITS(l2info.cookie) & ATM2_GAP_COUNT_MASK)) {
    697             ether_print(p, l2info.length, l2info.caplen);
    698             return l2info.header_len;
    699         }
    700 
    701         if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
    702             isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
    703             /* FIXME check if frame was recognized */
    704             return l2info.header_len;
    705         }
    706 
    707         if(juniper_ppp_heuristic_guess(p, l2info.length) != 0) /* PPPoA vcmux encaps ? */
    708             return l2info.header_len;
    709 
    710         if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
    711             return l2info.header_len;
    712 
    713 	return l2info.header_len;
    714 }
    715 #endif
    716 
    717 
    718 /* try to guess, based on all PPP protos that are supported in
    719  * a juniper router if the payload data is encapsulated using PPP */
    720 int
    721 juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
    722 
    723     switch(EXTRACT_16BITS(p)) {
    724     case PPP_IP :
    725     case PPP_OSI :
    726     case PPP_MPLS_UCAST :
    727     case PPP_MPLS_MCAST :
    728     case PPP_IPCP :
    729     case PPP_OSICP :
    730     case PPP_MPLSCP :
    731     case PPP_LCP :
    732     case PPP_PAP :
    733     case PPP_CHAP :
    734     case PPP_ML :
    735 #ifdef INET6
    736     case PPP_IPV6 :
    737     case PPP_IPV6CP :
    738 #endif
    739         ppp_print(p, length);
    740         break;
    741 
    742     default:
    743         return 0; /* did not find a ppp header */
    744         break;
    745     }
    746     return 1; /* we printed a ppp packet */
    747 }
    748 
    749 int
    750 ip_heuristic_guess(register const u_char *p, u_int length) {
    751 
    752     switch(p[0]) {
    753     case 0x45:
    754     case 0x46:
    755     case 0x47:
    756     case 0x48:
    757     case 0x49:
    758     case 0x4a:
    759     case 0x4b:
    760     case 0x4c:
    761     case 0x4d:
    762     case 0x4e:
    763     case 0x4f:
    764 	    ip_print(gndo, p, length);
    765 	    break;
    766 #ifdef INET6
    767     case 0x60:
    768     case 0x61:
    769     case 0x62:
    770     case 0x63:
    771     case 0x64:
    772     case 0x65:
    773     case 0x66:
    774     case 0x67:
    775     case 0x68:
    776     case 0x69:
    777     case 0x6a:
    778     case 0x6b:
    779     case 0x6c:
    780     case 0x6d:
    781     case 0x6e:
    782     case 0x6f:
    783         ip6_print(p, length);
    784         break;
    785 #endif
    786     default:
    787         return 0; /* did not find a ip header */
    788         break;
    789     }
    790     return 1; /* we printed an v4/v6 packet */
    791 }
    792 
    793 static int
    794 juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) {
    795 
    796     struct juniper_cookie_table_t *lp = juniper_cookie_table;
    797     u_int idx, offset;
    798 #ifdef DLT_JUNIPER_ATM2
    799     u_int32_t control_word;
    800 #endif
    801 
    802     l2info->header_len = 0;
    803     l2info->cookie_len = 0;
    804     l2info->proto = 0;
    805 
    806 
    807     l2info->length = h->len;
    808     l2info->caplen = h->caplen;
    809     l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
    810 
    811     TCHECK2(p[0],4);
    812     if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */
    813         printf("no magic-number found!");
    814         return 0;
    815     }
    816 
    817     if (eflag) /* print direction */
    818         printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction));
    819 
    820     /* extensions present ?  - calculate how much bytes to skip */
    821     if ((p[3] & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) {
    822         offset = 6 + EXTRACT_16BITS(p+4);
    823         if (eflag>1)
    824             printf("ext-len %u, ",EXTRACT_16BITS(p+4));
    825     } else
    826         offset = 4;
    827 
    828     if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
    829         if (eflag)
    830             printf("no-L2-hdr, ");
    831 
    832         /* there is no link-layer present -
    833          * perform the v4/v6 heuristics
    834          * to figure out what it is
    835          */
    836         TCHECK2(p[offset+4],1);
    837         if(ip_heuristic_guess(p+offset+4,l2info->length-(offset+4)) == 0)
    838             printf("no IP-hdr found!");
    839 
    840         l2info->header_len=offset+4;
    841         return 0; /* stop parsing the output further */
    842 
    843     }
    844     l2info->header_len = offset;
    845     p+=l2info->header_len;
    846     l2info->length -= l2info->header_len;
    847     l2info->caplen -= l2info->header_len;
    848 
    849     /* search through the cookie table and copy values matching for our PIC type */
    850     while (lp->s != NULL) {
    851         if (lp->pictype == l2info->pictype) {
    852 
    853             l2info->cookie_len += lp->cookie_len;
    854 
    855             switch (p[0]) {
    856             case LS_COOKIE_ID:
    857                 l2info->cookie_type = LS_COOKIE_ID;
    858                 l2info->cookie_len += 2;
    859                 break;
    860             case AS_COOKIE_ID:
    861                 l2info->cookie_type = AS_COOKIE_ID;
    862                 l2info->cookie_len = 8;
    863                 break;
    864 
    865             default:
    866                 l2info->bundle = l2info->cookie[0];
    867                 break;
    868             }
    869 
    870 
    871 #ifdef DLT_JUNIPER_MFR
    872             /* MFR child links don't carry cookies */
    873             if (l2info->pictype == DLT_JUNIPER_MFR &&
    874                 (p[0] & MFR_BE_MASK) == MFR_BE_MASK) {
    875                 l2info->cookie_len = 0;
    876             }
    877 #endif
    878 
    879             l2info->header_len += l2info->cookie_len;
    880             l2info->length -= l2info->cookie_len;
    881             l2info->caplen -= l2info->cookie_len;
    882 
    883             if (eflag)
    884                 printf("%s-PIC, cookie-len %u",
    885                        lp->s,
    886                        l2info->cookie_len);
    887 
    888             if (l2info->cookie_len > 0) {
    889                 TCHECK2(p[0],l2info->cookie_len);
    890                 if (eflag)
    891                     printf(", cookie 0x");
    892                 for (idx = 0; idx < l2info->cookie_len; idx++) {
    893                     l2info->cookie[idx] = p[idx]; /* copy cookie data */
    894                     if (eflag) printf("%02x",p[idx]);
    895                 }
    896             }
    897 
    898             if (eflag) printf(": "); /* print demarc b/w L2/L3*/
    899 
    900 
    901             l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len);
    902             break;
    903         }
    904         ++lp;
    905     }
    906     p+=l2info->cookie_len;
    907 
    908     /* DLT_ specific parsing */
    909     switch(l2info->pictype) {
    910 #ifdef DLT_JUNIPER_MLPPP
    911     case DLT_JUNIPER_MLPPP:
    912         switch (l2info->cookie_type) {
    913         case LS_COOKIE_ID:
    914             l2info->bundle = l2info->cookie[1];
    915             break;
    916         case AS_COOKIE_ID:
    917             l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
    918             l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
    919             break;
    920         default:
    921             l2info->bundle = l2info->cookie[0];
    922             break;
    923         }
    924         break;
    925 #endif
    926 #ifdef DLT_JUNIPER_MLFR
    927     case DLT_JUNIPER_MLFR:
    928         switch (l2info->cookie_type) {
    929         case LS_COOKIE_ID:
    930             l2info->bundle = l2info->cookie[1];
    931             l2info->proto = EXTRACT_16BITS(p);
    932             l2info->header_len += 2;
    933             l2info->length -= 2;
    934             l2info->caplen -= 2;
    935             break;
    936         case AS_COOKIE_ID:
    937             l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
    938             l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
    939             break;
    940         default:
    941             l2info->bundle = l2info->cookie[0];
    942             l2info->header_len += 2;
    943             l2info->length -= 2;
    944             l2info->caplen -= 2;
    945             break;
    946         }
    947         break;
    948 #endif
    949 #ifdef DLT_JUNIPER_MFR
    950     case DLT_JUNIPER_MFR:
    951         switch (l2info->cookie_type) {
    952         case LS_COOKIE_ID:
    953             l2info->bundle = l2info->cookie[1];
    954             l2info->proto = EXTRACT_16BITS(p);
    955             l2info->header_len += 2;
    956             l2info->length -= 2;
    957             l2info->caplen -= 2;
    958             break;
    959         case AS_COOKIE_ID:
    960             l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
    961             l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
    962             break;
    963         default:
    964             l2info->bundle = l2info->cookie[0];
    965             break;
    966         }
    967         break;
    968 #endif
    969 #ifdef DLT_JUNIPER_ATM2
    970     case DLT_JUNIPER_ATM2:
    971         TCHECK2(p[0],4);
    972         /* ATM cell relay control word present ? */
    973         if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK) {
    974             control_word = EXTRACT_32BITS(p);
    975             /* some control word heuristics */
    976             switch(control_word) {
    977             case 0: /* zero control word */
    978             case 0x08000000: /* < JUNOS 7.4 control-word */
    979             case 0x08380000: /* cntl word plus cell length (56) >= JUNOS 7.4*/
    980                 l2info->header_len += 4;
    981                 break;
    982             default:
    983                 break;
    984             }
    985 
    986             if (eflag)
    987                 printf("control-word 0x%08x ", control_word);
    988         }
    989         break;
    990 #endif
    991 #ifdef DLT_JUNIPER_ATM1
    992     case DLT_JUNIPER_ATM1:
    993         break;
    994 #endif
    995 #ifdef DLT_JUNIPER_PPP
    996     case DLT_JUNIPER_PPP:
    997         break;
    998 #endif
    999 #ifdef DLT_JUNIPER_CHDLC
   1000     case DLT_JUNIPER_CHDLC:
   1001         break;
   1002 #endif
   1003 #ifdef DLT_JUNIPER_ETHER
   1004     case DLT_JUNIPER_ETHER:
   1005         break;
   1006 #endif
   1007 #ifdef DLT_JUNIPER_FRELAY
   1008     case DLT_JUNIPER_FRELAY:
   1009         break;
   1010 #endif
   1011 
   1012     default:
   1013         printf("Unknown Juniper DLT_ type %u: ", l2info->pictype);
   1014         break;
   1015     }
   1016 
   1017     if (eflag > 1)
   1018         printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto);
   1019 
   1020     return 1; /* everything went ok so far. continue parsing */
   1021  trunc:
   1022     printf("[|juniper_hdr], length %u",h->len);
   1023     return 0;
   1024 }
   1025 
   1026 
   1027 /*
   1028  * Local Variables:
   1029  * c-style: whitesmith
   1030  * c-basic-offset: 4
   1031  * End:
   1032  */
   1033