Home | History | Annotate | Download | only in tcpdump
      1 /*     NetBSD: print-juniper.c,v 1.2 2007/07/24 11:53:45 drochner Exp        */
      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 Hannes Gredler (hannes (at) juniper.net)
     16  */
     17 
     18 /* \summary: DLT_JUNIPER_* printers */
     19 
     20 #ifndef lint
     21 #else
     22 __RCSID("NetBSD: print-juniper.c,v 1.3 2007/07/25 06:31:32 dogcow Exp ");
     23 #endif
     24 
     25 #ifdef HAVE_CONFIG_H
     26 #include "config.h"
     27 #endif
     28 
     29 #include <netdissect-stdinc.h>
     30 
     31 #include <string.h>
     32 
     33 #include "netdissect.h"
     34 #include "addrtoname.h"
     35 #include "extract.h"
     36 #include "ppp.h"
     37 #include "llc.h"
     38 #include "nlpid.h"
     39 #include "ethertype.h"
     40 #include "atm.h"
     41 
     42 #define JUNIPER_BPF_OUT           0       /* Outgoing packet */
     43 #define JUNIPER_BPF_IN            1       /* Incoming packet */
     44 #define JUNIPER_BPF_PKT_IN        0x1     /* Incoming packet */
     45 #define JUNIPER_BPF_NO_L2         0x2     /* L2 header stripped */
     46 #define JUNIPER_BPF_IIF           0x4     /* IIF is valid */
     47 #define JUNIPER_BPF_FILTER        0x40    /* BPF filtering is supported */
     48 #define JUNIPER_BPF_EXT           0x80    /* extensions present */
     49 #define JUNIPER_MGC_NUMBER        0x4d4743 /* = "MGC" */
     50 
     51 #define JUNIPER_LSQ_COOKIE_RE         (1 << 3)
     52 #define JUNIPER_LSQ_COOKIE_DIR        (1 << 2)
     53 #define JUNIPER_LSQ_L3_PROTO_SHIFT     4
     54 #define JUNIPER_LSQ_L3_PROTO_MASK     (0x17 << JUNIPER_LSQ_L3_PROTO_SHIFT)
     55 #define JUNIPER_LSQ_L3_PROTO_IPV4     (0 << JUNIPER_LSQ_L3_PROTO_SHIFT)
     56 #define JUNIPER_LSQ_L3_PROTO_IPV6     (1 << JUNIPER_LSQ_L3_PROTO_SHIFT)
     57 #define JUNIPER_LSQ_L3_PROTO_MPLS     (2 << JUNIPER_LSQ_L3_PROTO_SHIFT)
     58 #define JUNIPER_LSQ_L3_PROTO_ISO      (3 << JUNIPER_LSQ_L3_PROTO_SHIFT)
     59 #define AS_PIC_COOKIE_LEN 8
     60 
     61 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE 1
     62 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE 2
     63 #define JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE 3
     64 #define JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE 4
     65 #define JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE 5
     66 
     67 static const struct tok juniper_ipsec_type_values[] = {
     68     { JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE, "ESP ENCR-AUTH" },
     69     { JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE, "ESP ENCR-AH AUTH" },
     70     { JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE, "ESP AUTH" },
     71     { JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE, "AH AUTH" },
     72     { JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE, "ESP ENCR" },
     73     { 0, NULL}
     74 };
     75 
     76 static const struct tok juniper_direction_values[] = {
     77     { JUNIPER_BPF_IN,  "In"},
     78     { JUNIPER_BPF_OUT, "Out"},
     79     { 0, NULL}
     80 };
     81 
     82 /* codepoints for encoding extensions to a .pcap file */
     83 enum {
     84     JUNIPER_EXT_TLV_IFD_IDX = 1,
     85     JUNIPER_EXT_TLV_IFD_NAME = 2,
     86     JUNIPER_EXT_TLV_IFD_MEDIATYPE = 3,
     87     JUNIPER_EXT_TLV_IFL_IDX = 4,
     88     JUNIPER_EXT_TLV_IFL_UNIT = 5,
     89     JUNIPER_EXT_TLV_IFL_ENCAPS = 6,
     90     JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE = 7,
     91     JUNIPER_EXT_TLV_TTP_IFL_ENCAPS = 8
     92 };
     93 
     94 /* 1 byte type and 1-byte length */
     95 #define JUNIPER_EXT_TLV_OVERHEAD 2U
     96 
     97 static const struct tok jnx_ext_tlv_values[] = {
     98     { JUNIPER_EXT_TLV_IFD_IDX, "Device Interface Index" },
     99     { JUNIPER_EXT_TLV_IFD_NAME,"Device Interface Name" },
    100     { JUNIPER_EXT_TLV_IFD_MEDIATYPE, "Device Media Type" },
    101     { JUNIPER_EXT_TLV_IFL_IDX, "Logical Interface Index" },
    102     { JUNIPER_EXT_TLV_IFL_UNIT,"Logical Unit Number" },
    103     { JUNIPER_EXT_TLV_IFL_ENCAPS, "Logical Interface Encapsulation" },
    104     { JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE, "TTP derived Device Media Type" },
    105     { JUNIPER_EXT_TLV_TTP_IFL_ENCAPS, "TTP derived Logical Interface Encapsulation" },
    106     { 0, NULL }
    107 };
    108 
    109 static const struct tok jnx_flag_values[] = {
    110     { JUNIPER_BPF_EXT, "Ext" },
    111     { JUNIPER_BPF_FILTER, "Filter" },
    112     { JUNIPER_BPF_IIF, "IIF" },
    113     { JUNIPER_BPF_NO_L2, "no-L2" },
    114     { JUNIPER_BPF_PKT_IN, "In" },
    115     { 0, NULL }
    116 };
    117 
    118 #define JUNIPER_IFML_ETHER              1
    119 #define JUNIPER_IFML_FDDI               2
    120 #define JUNIPER_IFML_TOKENRING          3
    121 #define JUNIPER_IFML_PPP                4
    122 #define JUNIPER_IFML_FRAMERELAY         5
    123 #define JUNIPER_IFML_CISCOHDLC          6
    124 #define JUNIPER_IFML_SMDSDXI            7
    125 #define JUNIPER_IFML_ATMPVC             8
    126 #define JUNIPER_IFML_PPP_CCC            9
    127 #define JUNIPER_IFML_FRAMERELAY_CCC     10
    128 #define JUNIPER_IFML_IPIP               11
    129 #define JUNIPER_IFML_GRE                12
    130 #define JUNIPER_IFML_PIM                13
    131 #define JUNIPER_IFML_PIMD               14
    132 #define JUNIPER_IFML_CISCOHDLC_CCC      15
    133 #define JUNIPER_IFML_VLAN_CCC           16
    134 #define JUNIPER_IFML_MLPPP              17
    135 #define JUNIPER_IFML_MLFR               18
    136 #define JUNIPER_IFML_ML                 19
    137 #define JUNIPER_IFML_LSI                20
    138 #define JUNIPER_IFML_DFE                21
    139 #define JUNIPER_IFML_ATM_CELLRELAY_CCC  22
    140 #define JUNIPER_IFML_CRYPTO             23
    141 #define JUNIPER_IFML_GGSN               24
    142 #define JUNIPER_IFML_LSI_PPP            25
    143 #define JUNIPER_IFML_LSI_CISCOHDLC      26
    144 #define JUNIPER_IFML_PPP_TCC            27
    145 #define JUNIPER_IFML_FRAMERELAY_TCC     28
    146 #define JUNIPER_IFML_CISCOHDLC_TCC      29
    147 #define JUNIPER_IFML_ETHERNET_CCC       30
    148 #define JUNIPER_IFML_VT                 31
    149 #define JUNIPER_IFML_EXTENDED_VLAN_CCC  32
    150 #define JUNIPER_IFML_ETHER_OVER_ATM     33
    151 #define JUNIPER_IFML_MONITOR            34
    152 #define JUNIPER_IFML_ETHERNET_TCC       35
    153 #define JUNIPER_IFML_VLAN_TCC           36
    154 #define JUNIPER_IFML_EXTENDED_VLAN_TCC  37
    155 #define JUNIPER_IFML_CONTROLLER         38
    156 #define JUNIPER_IFML_MFR                39
    157 #define JUNIPER_IFML_LS                 40
    158 #define JUNIPER_IFML_ETHERNET_VPLS      41
    159 #define JUNIPER_IFML_ETHERNET_VLAN_VPLS 42
    160 #define JUNIPER_IFML_ETHERNET_EXTENDED_VLAN_VPLS 43
    161 #define JUNIPER_IFML_LT                 44
    162 #define JUNIPER_IFML_SERVICES           45
    163 #define JUNIPER_IFML_ETHER_VPLS_OVER_ATM 46
    164 #define JUNIPER_IFML_FR_PORT_CCC        47
    165 #define JUNIPER_IFML_FRAMERELAY_EXT_CCC 48
    166 #define JUNIPER_IFML_FRAMERELAY_EXT_TCC 49
    167 #define JUNIPER_IFML_FRAMERELAY_FLEX    50
    168 #define JUNIPER_IFML_GGSNI              51
    169 #define JUNIPER_IFML_ETHERNET_FLEX      52
    170 #define JUNIPER_IFML_COLLECTOR          53
    171 #define JUNIPER_IFML_AGGREGATOR         54
    172 #define JUNIPER_IFML_LAPD               55
    173 #define JUNIPER_IFML_PPPOE              56
    174 #define JUNIPER_IFML_PPP_SUBORDINATE    57
    175 #define JUNIPER_IFML_CISCOHDLC_SUBORDINATE  58
    176 #define JUNIPER_IFML_DFC                59
    177 #define JUNIPER_IFML_PICPEER            60
    178 
    179 static const struct tok juniper_ifmt_values[] = {
    180     { JUNIPER_IFML_ETHER, "Ethernet" },
    181     { JUNIPER_IFML_FDDI, "FDDI" },
    182     { JUNIPER_IFML_TOKENRING, "Token-Ring" },
    183     { JUNIPER_IFML_PPP, "PPP" },
    184     { JUNIPER_IFML_PPP_SUBORDINATE, "PPP-Subordinate" },
    185     { JUNIPER_IFML_FRAMERELAY, "Frame-Relay" },
    186     { JUNIPER_IFML_CISCOHDLC, "Cisco-HDLC" },
    187     { JUNIPER_IFML_SMDSDXI, "SMDS-DXI" },
    188     { JUNIPER_IFML_ATMPVC, "ATM-PVC" },
    189     { JUNIPER_IFML_PPP_CCC, "PPP-CCC" },
    190     { JUNIPER_IFML_FRAMERELAY_CCC, "Frame-Relay-CCC" },
    191     { JUNIPER_IFML_FRAMERELAY_EXT_CCC, "Extended FR-CCC" },
    192     { JUNIPER_IFML_IPIP, "IP-over-IP" },
    193     { JUNIPER_IFML_GRE, "GRE" },
    194     { JUNIPER_IFML_PIM, "PIM-Encapsulator" },
    195     { JUNIPER_IFML_PIMD, "PIM-Decapsulator" },
    196     { JUNIPER_IFML_CISCOHDLC_CCC, "Cisco-HDLC-CCC" },
    197     { JUNIPER_IFML_VLAN_CCC, "VLAN-CCC" },
    198     { JUNIPER_IFML_EXTENDED_VLAN_CCC, "Extended-VLAN-CCC" },
    199     { JUNIPER_IFML_MLPPP, "Multilink-PPP" },
    200     { JUNIPER_IFML_MLFR, "Multilink-FR" },
    201     { JUNIPER_IFML_MFR, "Multilink-FR-UNI-NNI" },
    202     { JUNIPER_IFML_ML, "Multilink" },
    203     { JUNIPER_IFML_LS, "LinkService" },
    204     { JUNIPER_IFML_LSI, "LSI" },
    205     { JUNIPER_IFML_ATM_CELLRELAY_CCC, "ATM-CCC-Cell-Relay" },
    206     { JUNIPER_IFML_CRYPTO, "IPSEC-over-IP" },
    207     { JUNIPER_IFML_GGSN, "GGSN" },
    208     { JUNIPER_IFML_PPP_TCC, "PPP-TCC" },
    209     { JUNIPER_IFML_FRAMERELAY_TCC, "Frame-Relay-TCC" },
    210     { JUNIPER_IFML_FRAMERELAY_EXT_TCC, "Extended FR-TCC" },
    211     { JUNIPER_IFML_CISCOHDLC_TCC, "Cisco-HDLC-TCC" },
    212     { JUNIPER_IFML_ETHERNET_CCC, "Ethernet-CCC" },
    213     { JUNIPER_IFML_VT, "VPN-Loopback-tunnel" },
    214     { JUNIPER_IFML_ETHER_OVER_ATM, "Ethernet-over-ATM" },
    215     { JUNIPER_IFML_ETHER_VPLS_OVER_ATM, "Ethernet-VPLS-over-ATM" },
    216     { JUNIPER_IFML_MONITOR, "Monitor" },
    217     { JUNIPER_IFML_ETHERNET_TCC, "Ethernet-TCC" },
    218     { JUNIPER_IFML_VLAN_TCC, "VLAN-TCC" },
    219     { JUNIPER_IFML_EXTENDED_VLAN_TCC, "Extended-VLAN-TCC" },
    220     { JUNIPER_IFML_CONTROLLER, "Controller" },
    221     { JUNIPER_IFML_ETHERNET_VPLS, "VPLS" },
    222     { JUNIPER_IFML_ETHERNET_VLAN_VPLS, "VLAN-VPLS" },
    223     { JUNIPER_IFML_ETHERNET_EXTENDED_VLAN_VPLS, "Extended-VLAN-VPLS" },
    224     { JUNIPER_IFML_LT, "Logical-tunnel" },
    225     { JUNIPER_IFML_SERVICES, "General-Services" },
    226     { JUNIPER_IFML_PPPOE, "PPPoE" },
    227     { JUNIPER_IFML_ETHERNET_FLEX, "Flexible-Ethernet-Services" },
    228     { JUNIPER_IFML_FRAMERELAY_FLEX, "Flexible-FrameRelay" },
    229     { JUNIPER_IFML_COLLECTOR, "Flow-collection" },
    230     { JUNIPER_IFML_PICPEER, "PIC Peer" },
    231     { JUNIPER_IFML_DFC, "Dynamic-Flow-Capture" },
    232     {0,                    NULL}
    233 };
    234 
    235 #define JUNIPER_IFLE_ATM_SNAP           2
    236 #define JUNIPER_IFLE_ATM_NLPID          3
    237 #define JUNIPER_IFLE_ATM_VCMUX          4
    238 #define JUNIPER_IFLE_ATM_LLC            5
    239 #define JUNIPER_IFLE_ATM_PPP_VCMUX      6
    240 #define JUNIPER_IFLE_ATM_PPP_LLC        7
    241 #define JUNIPER_IFLE_ATM_PPP_FUNI       8
    242 #define JUNIPER_IFLE_ATM_CCC            9
    243 #define JUNIPER_IFLE_FR_NLPID           10
    244 #define JUNIPER_IFLE_FR_SNAP            11
    245 #define JUNIPER_IFLE_FR_PPP             12
    246 #define JUNIPER_IFLE_FR_CCC             13
    247 #define JUNIPER_IFLE_ENET2              14
    248 #define JUNIPER_IFLE_IEEE8023_SNAP      15
    249 #define JUNIPER_IFLE_IEEE8023_LLC       16
    250 #define JUNIPER_IFLE_PPP                17
    251 #define JUNIPER_IFLE_CISCOHDLC          18
    252 #define JUNIPER_IFLE_PPP_CCC            19
    253 #define JUNIPER_IFLE_IPIP_NULL          20
    254 #define JUNIPER_IFLE_PIM_NULL           21
    255 #define JUNIPER_IFLE_GRE_NULL           22
    256 #define JUNIPER_IFLE_GRE_PPP            23
    257 #define JUNIPER_IFLE_PIMD_DECAPS        24
    258 #define JUNIPER_IFLE_CISCOHDLC_CCC      25
    259 #define JUNIPER_IFLE_ATM_CISCO_NLPID    26
    260 #define JUNIPER_IFLE_VLAN_CCC           27
    261 #define JUNIPER_IFLE_MLPPP              28
    262 #define JUNIPER_IFLE_MLFR               29
    263 #define JUNIPER_IFLE_LSI_NULL           30
    264 #define JUNIPER_IFLE_AGGREGATE_UNUSED   31
    265 #define JUNIPER_IFLE_ATM_CELLRELAY_CCC  32
    266 #define JUNIPER_IFLE_CRYPTO             33
    267 #define JUNIPER_IFLE_GGSN               34
    268 #define JUNIPER_IFLE_ATM_TCC            35
    269 #define JUNIPER_IFLE_FR_TCC             36
    270 #define JUNIPER_IFLE_PPP_TCC            37
    271 #define JUNIPER_IFLE_CISCOHDLC_TCC      38
    272 #define JUNIPER_IFLE_ETHERNET_CCC       39
    273 #define JUNIPER_IFLE_VT                 40
    274 #define JUNIPER_IFLE_ATM_EOA_LLC        41
    275 #define JUNIPER_IFLE_EXTENDED_VLAN_CCC          42
    276 #define JUNIPER_IFLE_ATM_SNAP_TCC       43
    277 #define JUNIPER_IFLE_MONITOR            44
    278 #define JUNIPER_IFLE_ETHERNET_TCC       45
    279 #define JUNIPER_IFLE_VLAN_TCC           46
    280 #define JUNIPER_IFLE_EXTENDED_VLAN_TCC  47
    281 #define JUNIPER_IFLE_MFR                48
    282 #define JUNIPER_IFLE_ETHERNET_VPLS      49
    283 #define JUNIPER_IFLE_ETHERNET_VLAN_VPLS 50
    284 #define JUNIPER_IFLE_ETHERNET_EXTENDED_VLAN_VPLS 51
    285 #define JUNIPER_IFLE_SERVICES           52
    286 #define JUNIPER_IFLE_ATM_ETHER_VPLS_ATM_LLC                53
    287 #define JUNIPER_IFLE_FR_PORT_CCC        54
    288 #define JUNIPER_IFLE_ATM_MLPPP_LLC      55
    289 #define JUNIPER_IFLE_ATM_EOA_CCC        56
    290 #define JUNIPER_IFLE_LT_VLAN            57
    291 #define JUNIPER_IFLE_COLLECTOR          58
    292 #define JUNIPER_IFLE_AGGREGATOR         59
    293 #define JUNIPER_IFLE_LAPD               60
    294 #define JUNIPER_IFLE_ATM_PPPOE_LLC          61
    295 #define JUNIPER_IFLE_ETHERNET_PPPOE         62
    296 #define JUNIPER_IFLE_PPPOE                  63
    297 #define JUNIPER_IFLE_PPP_SUBORDINATE        64
    298 #define JUNIPER_IFLE_CISCOHDLC_SUBORDINATE  65
    299 #define JUNIPER_IFLE_DFC                    66
    300 #define JUNIPER_IFLE_PICPEER                67
    301 
    302 static const struct tok juniper_ifle_values[] = {
    303     { JUNIPER_IFLE_AGGREGATOR, "Aggregator" },
    304     { JUNIPER_IFLE_ATM_CCC, "CCC over ATM" },
    305     { JUNIPER_IFLE_ATM_CELLRELAY_CCC, "ATM CCC Cell Relay" },
    306     { JUNIPER_IFLE_ATM_CISCO_NLPID, "CISCO compatible NLPID" },
    307     { JUNIPER_IFLE_ATM_EOA_CCC, "Ethernet over ATM CCC" },
    308     { JUNIPER_IFLE_ATM_EOA_LLC, "Ethernet over ATM LLC" },
    309     { JUNIPER_IFLE_ATM_ETHER_VPLS_ATM_LLC, "Ethernet VPLS over ATM LLC" },
    310     { JUNIPER_IFLE_ATM_LLC, "ATM LLC" },
    311     { JUNIPER_IFLE_ATM_MLPPP_LLC, "MLPPP over ATM LLC" },
    312     { JUNIPER_IFLE_ATM_NLPID, "ATM NLPID" },
    313     { JUNIPER_IFLE_ATM_PPPOE_LLC, "PPPoE over ATM LLC" },
    314     { JUNIPER_IFLE_ATM_PPP_FUNI, "PPP over FUNI" },
    315     { JUNIPER_IFLE_ATM_PPP_LLC, "PPP over ATM LLC" },
    316     { JUNIPER_IFLE_ATM_PPP_VCMUX, "PPP over ATM VCMUX" },
    317     { JUNIPER_IFLE_ATM_SNAP, "ATM SNAP" },
    318     { JUNIPER_IFLE_ATM_SNAP_TCC, "ATM SNAP TCC" },
    319     { JUNIPER_IFLE_ATM_TCC, "ATM VCMUX TCC" },
    320     { JUNIPER_IFLE_ATM_VCMUX, "ATM VCMUX" },
    321     { JUNIPER_IFLE_CISCOHDLC, "C-HDLC" },
    322     { JUNIPER_IFLE_CISCOHDLC_CCC, "C-HDLC CCC" },
    323     { JUNIPER_IFLE_CISCOHDLC_SUBORDINATE, "C-HDLC via dialer" },
    324     { JUNIPER_IFLE_CISCOHDLC_TCC, "C-HDLC TCC" },
    325     { JUNIPER_IFLE_COLLECTOR, "Collector" },
    326     { JUNIPER_IFLE_CRYPTO, "Crypto" },
    327     { JUNIPER_IFLE_ENET2, "Ethernet" },
    328     { JUNIPER_IFLE_ETHERNET_CCC, "Ethernet CCC" },
    329     { JUNIPER_IFLE_ETHERNET_EXTENDED_VLAN_VPLS, "Extended VLAN VPLS" },
    330     { JUNIPER_IFLE_ETHERNET_PPPOE, "PPPoE over Ethernet" },
    331     { JUNIPER_IFLE_ETHERNET_TCC, "Ethernet TCC" },
    332     { JUNIPER_IFLE_ETHERNET_VLAN_VPLS, "VLAN VPLS" },
    333     { JUNIPER_IFLE_ETHERNET_VPLS, "VPLS" },
    334     { JUNIPER_IFLE_EXTENDED_VLAN_CCC, "Extended VLAN CCC" },
    335     { JUNIPER_IFLE_EXTENDED_VLAN_TCC, "Extended VLAN TCC" },
    336     { JUNIPER_IFLE_FR_CCC, "FR CCC" },
    337     { JUNIPER_IFLE_FR_NLPID, "FR NLPID" },
    338     { JUNIPER_IFLE_FR_PORT_CCC, "FR CCC" },
    339     { JUNIPER_IFLE_FR_PPP, "FR PPP" },
    340     { JUNIPER_IFLE_FR_SNAP, "FR SNAP" },
    341     { JUNIPER_IFLE_FR_TCC, "FR TCC" },
    342     { JUNIPER_IFLE_GGSN, "GGSN" },
    343     { JUNIPER_IFLE_GRE_NULL, "GRE NULL" },
    344     { JUNIPER_IFLE_GRE_PPP, "PPP over GRE" },
    345     { JUNIPER_IFLE_IPIP_NULL, "IPIP" },
    346     { JUNIPER_IFLE_LAPD, "LAPD" },
    347     { JUNIPER_IFLE_LSI_NULL, "LSI Null" },
    348     { JUNIPER_IFLE_LT_VLAN, "LT VLAN" },
    349     { JUNIPER_IFLE_MFR, "MFR" },
    350     { JUNIPER_IFLE_MLFR, "MLFR" },
    351     { JUNIPER_IFLE_MLPPP, "MLPPP" },
    352     { JUNIPER_IFLE_MONITOR, "Monitor" },
    353     { JUNIPER_IFLE_PIMD_DECAPS, "PIMd" },
    354     { JUNIPER_IFLE_PIM_NULL, "PIM Null" },
    355     { JUNIPER_IFLE_PPP, "PPP" },
    356     { JUNIPER_IFLE_PPPOE, "PPPoE" },
    357     { JUNIPER_IFLE_PPP_CCC, "PPP CCC" },
    358     { JUNIPER_IFLE_PPP_SUBORDINATE, "" },
    359     { JUNIPER_IFLE_PPP_TCC, "PPP TCC" },
    360     { JUNIPER_IFLE_SERVICES, "General Services" },
    361     { JUNIPER_IFLE_VLAN_CCC, "VLAN CCC" },
    362     { JUNIPER_IFLE_VLAN_TCC, "VLAN TCC" },
    363     { JUNIPER_IFLE_VT, "VT" },
    364     {0,                    NULL}
    365 };
    366 
    367 struct juniper_cookie_table_t {
    368     uint32_t pictype;		/* pic type */
    369     uint8_t  cookie_len;       /* cookie len */
    370     const char *s;		/* pic name */
    371 };
    372 
    373 static const struct juniper_cookie_table_t juniper_cookie_table[] = {
    374 #ifdef DLT_JUNIPER_ATM1
    375     { DLT_JUNIPER_ATM1,  4, "ATM1"},
    376 #endif
    377 #ifdef DLT_JUNIPER_ATM2
    378     { DLT_JUNIPER_ATM2,  8, "ATM2"},
    379 #endif
    380 #ifdef DLT_JUNIPER_MLPPP
    381     { DLT_JUNIPER_MLPPP, 2, "MLPPP"},
    382 #endif
    383 #ifdef DLT_JUNIPER_MLFR
    384     { DLT_JUNIPER_MLFR,  2, "MLFR"},
    385 #endif
    386 #ifdef DLT_JUNIPER_MFR
    387     { DLT_JUNIPER_MFR,   4, "MFR"},
    388 #endif
    389 #ifdef DLT_JUNIPER_PPPOE
    390     { DLT_JUNIPER_PPPOE, 0, "PPPoE"},
    391 #endif
    392 #ifdef DLT_JUNIPER_PPPOE_ATM
    393     { DLT_JUNIPER_PPPOE_ATM, 0, "PPPoE ATM"},
    394 #endif
    395 #ifdef DLT_JUNIPER_GGSN
    396     { DLT_JUNIPER_GGSN, 8, "GGSN"},
    397 #endif
    398 #ifdef DLT_JUNIPER_MONITOR
    399     { DLT_JUNIPER_MONITOR, 8, "MONITOR"},
    400 #endif
    401 #ifdef DLT_JUNIPER_SERVICES
    402     { DLT_JUNIPER_SERVICES, 8, "AS"},
    403 #endif
    404 #ifdef DLT_JUNIPER_ES
    405     { DLT_JUNIPER_ES, 0, "ES"},
    406 #endif
    407     { 0, 0, NULL }
    408 };
    409 
    410 struct juniper_l2info_t {
    411     uint32_t length;
    412     uint32_t caplen;
    413     uint32_t pictype;
    414     uint8_t direction;
    415     uint8_t header_len;
    416     uint8_t cookie_len;
    417     uint8_t cookie_type;
    418     uint8_t cookie[8];
    419     uint8_t bundle;
    420     uint16_t proto;
    421     uint8_t flags;
    422 };
    423 
    424 #define LS_COOKIE_ID            0x54
    425 #define AS_COOKIE_ID            0x47
    426 #define LS_MLFR_COOKIE_LEN	4
    427 #define ML_MLFR_COOKIE_LEN	2
    428 #define LS_MFR_COOKIE_LEN	6
    429 #define ATM1_COOKIE_LEN         4
    430 #define ATM2_COOKIE_LEN         8
    431 
    432 #define ATM2_PKT_TYPE_MASK  0x70
    433 #define ATM2_GAP_COUNT_MASK 0x3F
    434 
    435 #define JUNIPER_PROTO_NULL          1
    436 #define JUNIPER_PROTO_IPV4          2
    437 #define JUNIPER_PROTO_IPV6          6
    438 
    439 #define MFR_BE_MASK 0xc0
    440 
    441 static const struct tok juniper_protocol_values[] = {
    442     { JUNIPER_PROTO_NULL, "Null" },
    443     { JUNIPER_PROTO_IPV4, "IPv4" },
    444     { JUNIPER_PROTO_IPV6, "IPv6" },
    445     { 0, NULL}
    446 };
    447 
    448 static int ip_heuristic_guess(netdissect_options *, register const u_char *, u_int);
    449 static int juniper_ppp_heuristic_guess(netdissect_options *, register const u_char *, u_int);
    450 static int juniper_parse_header(netdissect_options *, const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
    451 
    452 #ifdef DLT_JUNIPER_GGSN
    453 u_int
    454 juniper_ggsn_print(netdissect_options *ndo,
    455                    const struct pcap_pkthdr *h, register const u_char *p)
    456 {
    457         struct juniper_l2info_t l2info;
    458         struct juniper_ggsn_header {
    459             uint8_t svc_id;
    460             uint8_t flags_len;
    461             uint8_t proto;
    462             uint8_t flags;
    463             uint8_t vlan_id[2];
    464             uint8_t res[2];
    465         };
    466         const struct juniper_ggsn_header *gh;
    467 
    468         l2info.pictype = DLT_JUNIPER_GGSN;
    469         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    470             return l2info.header_len;
    471 
    472         p+=l2info.header_len;
    473         gh = (struct juniper_ggsn_header *)&l2info.cookie;
    474 
    475         if (ndo->ndo_eflag) {
    476             ND_PRINT((ndo, "proto %s (%u), vlan %u: ",
    477                    tok2str(juniper_protocol_values,"Unknown",gh->proto),
    478                    gh->proto,
    479                    EXTRACT_16BITS(&gh->vlan_id[0])));
    480         }
    481 
    482         switch (gh->proto) {
    483         case JUNIPER_PROTO_IPV4:
    484             ip_print(ndo, p, l2info.length);
    485             break;
    486         case JUNIPER_PROTO_IPV6:
    487             ip6_print(ndo, p, l2info.length);
    488             break;
    489         default:
    490             if (!ndo->ndo_eflag)
    491                 ND_PRINT((ndo, "unknown GGSN proto (%u)", gh->proto));
    492         }
    493 
    494         return l2info.header_len;
    495 }
    496 #endif
    497 
    498 #ifdef DLT_JUNIPER_ES
    499 u_int
    500 juniper_es_print(netdissect_options *ndo,
    501                  const struct pcap_pkthdr *h, register const u_char *p)
    502 {
    503         struct juniper_l2info_t l2info;
    504         struct juniper_ipsec_header {
    505             uint8_t sa_index[2];
    506             uint8_t ttl;
    507             uint8_t type;
    508             uint8_t spi[4];
    509             uint8_t src_ip[4];
    510             uint8_t dst_ip[4];
    511         };
    512         u_int rewrite_len,es_type_bundle;
    513         const struct juniper_ipsec_header *ih;
    514 
    515         l2info.pictype = DLT_JUNIPER_ES;
    516         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    517             return l2info.header_len;
    518 
    519         p+=l2info.header_len;
    520         ih = (const struct juniper_ipsec_header *)p;
    521 
    522         switch (ih->type) {
    523         case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE:
    524         case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE:
    525             rewrite_len = 0;
    526             es_type_bundle = 1;
    527             break;
    528         case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE:
    529         case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE:
    530         case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE:
    531             rewrite_len = 16;
    532             es_type_bundle = 0;
    533             break;
    534         default:
    535             ND_PRINT((ndo, "ES Invalid type %u, length %u",
    536                    ih->type,
    537                    l2info.length));
    538             return l2info.header_len;
    539         }
    540 
    541         l2info.length-=rewrite_len;
    542         p+=rewrite_len;
    543 
    544         if (ndo->ndo_eflag) {
    545             if (!es_type_bundle) {
    546                 ND_PRINT((ndo, "ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n",
    547                        EXTRACT_16BITS(&ih->sa_index),
    548                        ih->ttl,
    549                        tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
    550                        ih->type,
    551                        EXTRACT_32BITS(&ih->spi),
    552                        ipaddr_string(ndo, &ih->src_ip),
    553                        ipaddr_string(ndo, &ih->dst_ip),
    554                        l2info.length));
    555             } else {
    556                 ND_PRINT((ndo, "ES SA, index %u, ttl %u type %s (%u), length %u\n",
    557                        EXTRACT_16BITS(&ih->sa_index),
    558                        ih->ttl,
    559                        tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
    560                        ih->type,
    561                        l2info.length));
    562             }
    563         }
    564 
    565         ip_print(ndo, p, l2info.length);
    566         return l2info.header_len;
    567 }
    568 #endif
    569 
    570 #ifdef DLT_JUNIPER_MONITOR
    571 u_int
    572 juniper_monitor_print(netdissect_options *ndo,
    573                       const struct pcap_pkthdr *h, register const u_char *p)
    574 {
    575         struct juniper_l2info_t l2info;
    576         struct juniper_monitor_header {
    577             uint8_t pkt_type;
    578             uint8_t padding;
    579             uint8_t iif[2];
    580             uint8_t service_id[4];
    581         };
    582         const struct juniper_monitor_header *mh;
    583 
    584         l2info.pictype = DLT_JUNIPER_MONITOR;
    585         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    586             return l2info.header_len;
    587 
    588         p+=l2info.header_len;
    589         mh = (const struct juniper_monitor_header *)p;
    590 
    591         if (ndo->ndo_eflag)
    592             ND_PRINT((ndo, "service-id %u, iif %u, pkt-type %u: ",
    593                    EXTRACT_32BITS(&mh->service_id),
    594                    EXTRACT_16BITS(&mh->iif),
    595                    mh->pkt_type));
    596 
    597         /* no proto field - lets guess by first byte of IP header*/
    598         ip_heuristic_guess (ndo, p, l2info.length);
    599 
    600         return l2info.header_len;
    601 }
    602 #endif
    603 
    604 #ifdef DLT_JUNIPER_SERVICES
    605 u_int
    606 juniper_services_print(netdissect_options *ndo,
    607                        const struct pcap_pkthdr *h, register const u_char *p)
    608 {
    609         struct juniper_l2info_t l2info;
    610         struct juniper_services_header {
    611             uint8_t svc_id;
    612             uint8_t flags_len;
    613             uint8_t svc_set_id[2];
    614             uint8_t dir_iif[4];
    615         };
    616         const struct juniper_services_header *sh;
    617 
    618         l2info.pictype = DLT_JUNIPER_SERVICES;
    619         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    620             return l2info.header_len;
    621 
    622         p+=l2info.header_len;
    623         sh = (const struct juniper_services_header *)p;
    624 
    625         if (ndo->ndo_eflag)
    626             ND_PRINT((ndo, "service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ",
    627                    sh->svc_id,
    628                    sh->flags_len,
    629                    EXTRACT_16BITS(&sh->svc_set_id),
    630                    EXTRACT_24BITS(&sh->dir_iif[1])));
    631 
    632         /* no proto field - lets guess by first byte of IP header*/
    633         ip_heuristic_guess (ndo, p, l2info.length);
    634 
    635         return l2info.header_len;
    636 }
    637 #endif
    638 
    639 #ifdef DLT_JUNIPER_PPPOE
    640 u_int
    641 juniper_pppoe_print(netdissect_options *ndo,
    642                     const struct pcap_pkthdr *h, register const u_char *p)
    643 {
    644         struct juniper_l2info_t l2info;
    645 
    646         l2info.pictype = DLT_JUNIPER_PPPOE;
    647         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    648             return l2info.header_len;
    649 
    650         p+=l2info.header_len;
    651         /* this DLT contains nothing but raw ethernet frames */
    652         ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
    653         return l2info.header_len;
    654 }
    655 #endif
    656 
    657 #ifdef DLT_JUNIPER_ETHER
    658 u_int
    659 juniper_ether_print(netdissect_options *ndo,
    660                     const struct pcap_pkthdr *h, register const u_char *p)
    661 {
    662         struct juniper_l2info_t l2info;
    663 
    664         l2info.pictype = DLT_JUNIPER_ETHER;
    665         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    666             return l2info.header_len;
    667 
    668         p+=l2info.header_len;
    669         /* this DLT contains nothing but raw Ethernet frames */
    670         ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
    671         return l2info.header_len;
    672 }
    673 #endif
    674 
    675 #ifdef DLT_JUNIPER_PPP
    676 u_int
    677 juniper_ppp_print(netdissect_options *ndo,
    678                   const struct pcap_pkthdr *h, register const u_char *p)
    679 {
    680         struct juniper_l2info_t l2info;
    681 
    682         l2info.pictype = DLT_JUNIPER_PPP;
    683         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    684             return l2info.header_len;
    685 
    686         p+=l2info.header_len;
    687         /* this DLT contains nothing but raw ppp frames */
    688         ppp_print(ndo, p, l2info.length);
    689         return l2info.header_len;
    690 }
    691 #endif
    692 
    693 #ifdef DLT_JUNIPER_FRELAY
    694 u_int
    695 juniper_frelay_print(netdissect_options *ndo,
    696                      const struct pcap_pkthdr *h, register const u_char *p)
    697 {
    698         struct juniper_l2info_t l2info;
    699 
    700         l2info.pictype = DLT_JUNIPER_FRELAY;
    701         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    702             return l2info.header_len;
    703 
    704         p+=l2info.header_len;
    705         /* this DLT contains nothing but raw frame-relay frames */
    706         fr_print(ndo, p, l2info.length);
    707         return l2info.header_len;
    708 }
    709 #endif
    710 
    711 #ifdef DLT_JUNIPER_CHDLC
    712 u_int
    713 juniper_chdlc_print(netdissect_options *ndo,
    714                     const struct pcap_pkthdr *h, register const u_char *p)
    715 {
    716         struct juniper_l2info_t l2info;
    717 
    718         l2info.pictype = DLT_JUNIPER_CHDLC;
    719         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    720             return l2info.header_len;
    721 
    722         p+=l2info.header_len;
    723         /* this DLT contains nothing but raw c-hdlc frames */
    724         chdlc_print(ndo, p, l2info.length);
    725         return l2info.header_len;
    726 }
    727 #endif
    728 
    729 #ifdef DLT_JUNIPER_PPPOE_ATM
    730 u_int
    731 juniper_pppoe_atm_print(netdissect_options *ndo,
    732                         const struct pcap_pkthdr *h, register const u_char *p)
    733 {
    734         struct juniper_l2info_t l2info;
    735 	uint16_t extracted_ethertype;
    736 
    737         l2info.pictype = DLT_JUNIPER_PPPOE_ATM;
    738         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    739             return l2info.header_len;
    740 
    741         p+=l2info.header_len;
    742 
    743         extracted_ethertype = EXTRACT_16BITS(p);
    744         /* this DLT contains nothing but raw PPPoE frames,
    745          * prepended with a type field*/
    746         if (ethertype_print(ndo, extracted_ethertype,
    747                               p+ETHERTYPE_LEN,
    748                               l2info.length-ETHERTYPE_LEN,
    749                               l2info.caplen-ETHERTYPE_LEN,
    750                               NULL, NULL) == 0)
    751             /* ether_type not known, probably it wasn't one */
    752             ND_PRINT((ndo, "unknown ethertype 0x%04x", extracted_ethertype));
    753 
    754         return l2info.header_len;
    755 }
    756 #endif
    757 
    758 #ifdef DLT_JUNIPER_MLPPP
    759 u_int
    760 juniper_mlppp_print(netdissect_options *ndo,
    761                     const struct pcap_pkthdr *h, register const u_char *p)
    762 {
    763         struct juniper_l2info_t l2info;
    764 
    765         l2info.pictype = DLT_JUNIPER_MLPPP;
    766         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    767             return l2info.header_len;
    768 
    769         /* suppress Bundle-ID if frame was captured on a child-link
    770          * best indicator if the cookie looks like a proto */
    771         if (ndo->ndo_eflag &&
    772             EXTRACT_16BITS(&l2info.cookie) != PPP_OSI &&
    773             EXTRACT_16BITS(&l2info.cookie) !=  (PPP_ADDRESS << 8 | PPP_CONTROL))
    774             ND_PRINT((ndo, "Bundle-ID %u: ", l2info.bundle));
    775 
    776         p+=l2info.header_len;
    777 
    778         /* first try the LSQ protos */
    779         switch(l2info.proto) {
    780         case JUNIPER_LSQ_L3_PROTO_IPV4:
    781             /* IP traffic going to the RE would not have a cookie
    782              * -> this must be incoming IS-IS over PPP
    783              */
    784             if (l2info.cookie[4] == (JUNIPER_LSQ_COOKIE_RE|JUNIPER_LSQ_COOKIE_DIR))
    785                 ppp_print(ndo, p, l2info.length);
    786             else
    787                 ip_print(ndo, p, l2info.length);
    788             return l2info.header_len;
    789         case JUNIPER_LSQ_L3_PROTO_IPV6:
    790             ip6_print(ndo, p,l2info.length);
    791             return l2info.header_len;
    792         case JUNIPER_LSQ_L3_PROTO_MPLS:
    793             mpls_print(ndo, p, l2info.length);
    794             return l2info.header_len;
    795         case JUNIPER_LSQ_L3_PROTO_ISO:
    796             isoclns_print(ndo, p, l2info.length, l2info.caplen);
    797             return l2info.header_len;
    798         default:
    799             break;
    800         }
    801 
    802         /* zero length cookie ? */
    803         switch (EXTRACT_16BITS(&l2info.cookie)) {
    804         case PPP_OSI:
    805             ppp_print(ndo, p - 2, l2info.length + 2);
    806             break;
    807         case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */
    808         default:
    809             ppp_print(ndo, p, l2info.length);
    810             break;
    811         }
    812 
    813         return l2info.header_len;
    814 }
    815 #endif
    816 
    817 
    818 #ifdef DLT_JUNIPER_MFR
    819 u_int
    820 juniper_mfr_print(netdissect_options *ndo,
    821                   const struct pcap_pkthdr *h, register const u_char *p)
    822 {
    823         struct juniper_l2info_t l2info;
    824 
    825         memset(&l2info, 0, sizeof(l2info));
    826         l2info.pictype = DLT_JUNIPER_MFR;
    827         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    828             return l2info.header_len;
    829 
    830         p+=l2info.header_len;
    831 
    832         /* child-link ? */
    833         if (l2info.cookie_len == 0) {
    834             mfr_print(ndo, p, l2info.length);
    835             return l2info.header_len;
    836         }
    837 
    838         /* first try the LSQ protos */
    839         if (l2info.cookie_len == AS_PIC_COOKIE_LEN) {
    840             switch(l2info.proto) {
    841             case JUNIPER_LSQ_L3_PROTO_IPV4:
    842                 ip_print(ndo, p, l2info.length);
    843                 return l2info.header_len;
    844             case JUNIPER_LSQ_L3_PROTO_IPV6:
    845                 ip6_print(ndo, p,l2info.length);
    846                 return l2info.header_len;
    847             case JUNIPER_LSQ_L3_PROTO_MPLS:
    848                 mpls_print(ndo, p, l2info.length);
    849                 return l2info.header_len;
    850             case JUNIPER_LSQ_L3_PROTO_ISO:
    851                 isoclns_print(ndo, p, l2info.length, l2info.caplen);
    852                 return l2info.header_len;
    853             default:
    854                 break;
    855             }
    856             return l2info.header_len;
    857         }
    858 
    859         /* suppress Bundle-ID if frame was captured on a child-link */
    860         if (ndo->ndo_eflag && EXTRACT_32BITS(l2info.cookie) != 1)
    861             ND_PRINT((ndo, "Bundle-ID %u, ", l2info.bundle));
    862         switch (l2info.proto) {
    863         case (LLCSAP_ISONS<<8 | LLCSAP_ISONS):
    864             isoclns_print(ndo, p + 1, l2info.length - 1, l2info.caplen - 1);
    865             break;
    866         case (LLC_UI<<8 | NLPID_Q933):
    867         case (LLC_UI<<8 | NLPID_IP):
    868         case (LLC_UI<<8 | NLPID_IP6):
    869             /* pass IP{4,6} to the OSI layer for proper link-layer printing */
    870             isoclns_print(ndo, p - 1, l2info.length + 1, l2info.caplen + 1);
    871             break;
    872         default:
    873             ND_PRINT((ndo, "unknown protocol 0x%04x, length %u", l2info.proto, l2info.length));
    874         }
    875 
    876         return l2info.header_len;
    877 }
    878 #endif
    879 
    880 #ifdef DLT_JUNIPER_MLFR
    881 u_int
    882 juniper_mlfr_print(netdissect_options *ndo,
    883                    const struct pcap_pkthdr *h, register const u_char *p)
    884 {
    885         struct juniper_l2info_t l2info;
    886 
    887         l2info.pictype = DLT_JUNIPER_MLFR;
    888         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    889             return l2info.header_len;
    890 
    891         p+=l2info.header_len;
    892 
    893         /* suppress Bundle-ID if frame was captured on a child-link */
    894         if (ndo->ndo_eflag && EXTRACT_32BITS(l2info.cookie) != 1)
    895             ND_PRINT((ndo, "Bundle-ID %u, ", l2info.bundle));
    896         switch (l2info.proto) {
    897         case (LLC_UI):
    898         case (LLC_UI<<8):
    899             isoclns_print(ndo, p, l2info.length, l2info.caplen);
    900             break;
    901         case (LLC_UI<<8 | NLPID_Q933):
    902         case (LLC_UI<<8 | NLPID_IP):
    903         case (LLC_UI<<8 | NLPID_IP6):
    904             /* pass IP{4,6} to the OSI layer for proper link-layer printing */
    905             isoclns_print(ndo, p - 1, l2info.length + 1, l2info.caplen + 1);
    906             break;
    907         default:
    908             ND_PRINT((ndo, "unknown protocol 0x%04x, length %u", l2info.proto, l2info.length));
    909         }
    910 
    911         return l2info.header_len;
    912 }
    913 #endif
    914 
    915 /*
    916  *     ATM1 PIC cookie format
    917  *
    918  *     +-----+-------------------------+-------------------------------+
    919  *     |fmtid|     vc index            |  channel  ID                  |
    920  *     +-----+-------------------------+-------------------------------+
    921  */
    922 
    923 #ifdef DLT_JUNIPER_ATM1
    924 u_int
    925 juniper_atm1_print(netdissect_options *ndo,
    926                    const struct pcap_pkthdr *h, register const u_char *p)
    927 {
    928         int llc_hdrlen;
    929 
    930         struct juniper_l2info_t l2info;
    931 
    932         l2info.pictype = DLT_JUNIPER_ATM1;
    933         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    934             return l2info.header_len;
    935 
    936         p+=l2info.header_len;
    937 
    938         if (l2info.cookie[0] == 0x80) { /* OAM cell ? */
    939             oam_print(ndo, p, l2info.length, ATM_OAM_NOHEC);
    940             return l2info.header_len;
    941         }
    942 
    943         if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
    944             EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
    945 
    946             llc_hdrlen = llc_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
    947             if (llc_hdrlen > 0)
    948                 return l2info.header_len;
    949         }
    950 
    951         if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
    952             isoclns_print(ndo, p + 1, l2info.length - 1, l2info.caplen - 1);
    953             /* FIXME check if frame was recognized */
    954             return l2info.header_len;
    955         }
    956 
    957         if (ip_heuristic_guess(ndo, p, l2info.length) != 0) /* last try - vcmux encaps ? */
    958             return l2info.header_len;
    959 
    960 	return l2info.header_len;
    961 }
    962 #endif
    963 
    964 /*
    965  *     ATM2 PIC cookie format
    966  *
    967  *     +-------------------------------+---------+---+-----+-----------+
    968  *     |     channel ID                |  reserv |AAL| CCRQ| gap cnt   |
    969  *     +-------------------------------+---------+---+-----+-----------+
    970  */
    971 
    972 #ifdef DLT_JUNIPER_ATM2
    973 u_int
    974 juniper_atm2_print(netdissect_options *ndo,
    975                    const struct pcap_pkthdr *h, register const u_char *p)
    976 {
    977         int llc_hdrlen;
    978 
    979         struct juniper_l2info_t l2info;
    980 
    981         l2info.pictype = DLT_JUNIPER_ATM2;
    982         if (juniper_parse_header(ndo, p, h, &l2info) == 0)
    983             return l2info.header_len;
    984 
    985         p+=l2info.header_len;
    986 
    987         if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
    988             oam_print(ndo, p, l2info.length, ATM_OAM_NOHEC);
    989             return l2info.header_len;
    990         }
    991 
    992         if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
    993             EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
    994 
    995             llc_hdrlen = llc_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
    996             if (llc_hdrlen > 0)
    997                 return l2info.header_len;
    998         }
    999 
   1000         if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
   1001             (EXTRACT_32BITS(l2info.cookie) & ATM2_GAP_COUNT_MASK)) {
   1002             ether_print(ndo, p, l2info.length, l2info.caplen, NULL, NULL);
   1003             return l2info.header_len;
   1004         }
   1005 
   1006         if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
   1007             isoclns_print(ndo, p + 1, l2info.length - 1, l2info.caplen - 1);
   1008             /* FIXME check if frame was recognized */
   1009             return l2info.header_len;
   1010         }
   1011 
   1012         if(juniper_ppp_heuristic_guess(ndo, p, l2info.length) != 0) /* PPPoA vcmux encaps ? */
   1013             return l2info.header_len;
   1014 
   1015         if (ip_heuristic_guess(ndo, p, l2info.length) != 0) /* last try - vcmux encaps ? */
   1016             return l2info.header_len;
   1017 
   1018 	return l2info.header_len;
   1019 }
   1020 #endif
   1021 
   1022 
   1023 /* try to guess, based on all PPP protos that are supported in
   1024  * a juniper router if the payload data is encapsulated using PPP */
   1025 static int
   1026 juniper_ppp_heuristic_guess(netdissect_options *ndo,
   1027                             register const u_char *p, u_int length)
   1028 {
   1029     switch(EXTRACT_16BITS(p)) {
   1030     case PPP_IP :
   1031     case PPP_OSI :
   1032     case PPP_MPLS_UCAST :
   1033     case PPP_MPLS_MCAST :
   1034     case PPP_IPCP :
   1035     case PPP_OSICP :
   1036     case PPP_MPLSCP :
   1037     case PPP_LCP :
   1038     case PPP_PAP :
   1039     case PPP_CHAP :
   1040     case PPP_ML :
   1041     case PPP_IPV6 :
   1042     case PPP_IPV6CP :
   1043         ppp_print(ndo, p, length);
   1044         break;
   1045 
   1046     default:
   1047         return 0; /* did not find a ppp header */
   1048         break;
   1049     }
   1050     return 1; /* we printed a ppp packet */
   1051 }
   1052 
   1053 static int
   1054 ip_heuristic_guess(netdissect_options *ndo,
   1055                    register const u_char *p, u_int length)
   1056 {
   1057     switch(p[0]) {
   1058     case 0x45:
   1059     case 0x46:
   1060     case 0x47:
   1061     case 0x48:
   1062     case 0x49:
   1063     case 0x4a:
   1064     case 0x4b:
   1065     case 0x4c:
   1066     case 0x4d:
   1067     case 0x4e:
   1068     case 0x4f:
   1069 	    ip_print(ndo, p, length);
   1070 	    break;
   1071     case 0x60:
   1072     case 0x61:
   1073     case 0x62:
   1074     case 0x63:
   1075     case 0x64:
   1076     case 0x65:
   1077     case 0x66:
   1078     case 0x67:
   1079     case 0x68:
   1080     case 0x69:
   1081     case 0x6a:
   1082     case 0x6b:
   1083     case 0x6c:
   1084     case 0x6d:
   1085     case 0x6e:
   1086     case 0x6f:
   1087         ip6_print(ndo, p, length);
   1088         break;
   1089     default:
   1090         return 0; /* did not find a ip header */
   1091         break;
   1092     }
   1093     return 1; /* we printed an v4/v6 packet */
   1094 }
   1095 
   1096 static int
   1097 juniper_read_tlv_value(const u_char *p, u_int tlv_type, u_int tlv_len)
   1098 {
   1099    int tlv_value;
   1100 
   1101    /* TLVs < 128 are little endian encoded */
   1102    if (tlv_type < 128) {
   1103        switch (tlv_len) {
   1104        case 1:
   1105            tlv_value = *p;
   1106            break;
   1107        case 2:
   1108            tlv_value = EXTRACT_LE_16BITS(p);
   1109            break;
   1110        case 3:
   1111            tlv_value = EXTRACT_LE_24BITS(p);
   1112            break;
   1113        case 4:
   1114            tlv_value = EXTRACT_LE_32BITS(p);
   1115            break;
   1116        default:
   1117            tlv_value = -1;
   1118            break;
   1119        }
   1120    } else {
   1121        /* TLVs >= 128 are big endian encoded */
   1122        switch (tlv_len) {
   1123        case 1:
   1124            tlv_value = *p;
   1125            break;
   1126        case 2:
   1127            tlv_value = EXTRACT_16BITS(p);
   1128            break;
   1129        case 3:
   1130            tlv_value = EXTRACT_24BITS(p);
   1131            break;
   1132        case 4:
   1133            tlv_value = EXTRACT_32BITS(p);
   1134            break;
   1135        default:
   1136            tlv_value = -1;
   1137            break;
   1138        }
   1139    }
   1140    return tlv_value;
   1141 }
   1142 
   1143 static int
   1144 juniper_parse_header(netdissect_options *ndo,
   1145                      const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info)
   1146 {
   1147     const struct juniper_cookie_table_t *lp = juniper_cookie_table;
   1148     u_int idx, jnx_ext_len, jnx_header_len = 0;
   1149     uint8_t tlv_type,tlv_len;
   1150     uint32_t control_word;
   1151     int tlv_value;
   1152     const u_char *tptr;
   1153 
   1154 
   1155     l2info->header_len = 0;
   1156     l2info->cookie_len = 0;
   1157     l2info->proto = 0;
   1158 
   1159 
   1160     l2info->length = h->len;
   1161     l2info->caplen = h->caplen;
   1162     ND_TCHECK2(p[0], 4);
   1163     l2info->flags = p[3];
   1164     l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
   1165 
   1166     if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */
   1167         ND_PRINT((ndo, "no magic-number found!"));
   1168         return 0;
   1169     }
   1170 
   1171     if (ndo->ndo_eflag) /* print direction */
   1172         ND_PRINT((ndo, "%3s ", tok2str(juniper_direction_values, "---", l2info->direction)));
   1173 
   1174     /* magic number + flags */
   1175     jnx_header_len = 4;
   1176 
   1177     if (ndo->ndo_vflag > 1)
   1178         ND_PRINT((ndo, "\n\tJuniper PCAP Flags [%s]",
   1179                bittok2str(jnx_flag_values, "none", l2info->flags)));
   1180 
   1181     /* extensions present ?  - calculate how much bytes to skip */
   1182     if ((l2info->flags & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) {
   1183 
   1184         tptr = p+jnx_header_len;
   1185 
   1186         /* ok to read extension length ? */
   1187         ND_TCHECK2(tptr[0], 2);
   1188         jnx_ext_len = EXTRACT_16BITS(tptr);
   1189         jnx_header_len += 2;
   1190         tptr +=2;
   1191 
   1192         /* nail up the total length -
   1193          * just in case something goes wrong
   1194          * with TLV parsing */
   1195         jnx_header_len += jnx_ext_len;
   1196 
   1197         if (ndo->ndo_vflag > 1)
   1198             ND_PRINT((ndo, ", PCAP Extension(s) total length %u", jnx_ext_len));
   1199 
   1200         ND_TCHECK2(tptr[0], jnx_ext_len);
   1201         while (jnx_ext_len > JUNIPER_EXT_TLV_OVERHEAD) {
   1202             tlv_type = *(tptr++);
   1203             tlv_len = *(tptr++);
   1204             tlv_value = 0;
   1205 
   1206             /* sanity checks */
   1207             if (tlv_type == 0 || tlv_len == 0)
   1208                 break;
   1209             if (tlv_len+JUNIPER_EXT_TLV_OVERHEAD > jnx_ext_len)
   1210                 goto trunc;
   1211 
   1212             if (ndo->ndo_vflag > 1)
   1213                 ND_PRINT((ndo, "\n\t  %s Extension TLV #%u, length %u, value ",
   1214                        tok2str(jnx_ext_tlv_values,"Unknown",tlv_type),
   1215                        tlv_type,
   1216                        tlv_len));
   1217 
   1218             tlv_value = juniper_read_tlv_value(tptr, tlv_type, tlv_len);
   1219             switch (tlv_type) {
   1220             case JUNIPER_EXT_TLV_IFD_NAME:
   1221                 /* FIXME */
   1222                 break;
   1223             case JUNIPER_EXT_TLV_IFD_MEDIATYPE:
   1224             case JUNIPER_EXT_TLV_TTP_IFD_MEDIATYPE:
   1225                 if (tlv_value != -1) {
   1226                     if (ndo->ndo_vflag > 1)
   1227                         ND_PRINT((ndo, "%s (%u)",
   1228                                tok2str(juniper_ifmt_values, "Unknown", tlv_value),
   1229                                tlv_value));
   1230                 }
   1231                 break;
   1232             case JUNIPER_EXT_TLV_IFL_ENCAPS:
   1233             case JUNIPER_EXT_TLV_TTP_IFL_ENCAPS:
   1234                 if (tlv_value != -1) {
   1235                     if (ndo->ndo_vflag > 1)
   1236                         ND_PRINT((ndo, "%s (%u)",
   1237                                tok2str(juniper_ifle_values, "Unknown", tlv_value),
   1238                                tlv_value));
   1239                 }
   1240                 break;
   1241             case JUNIPER_EXT_TLV_IFL_IDX: /* fall through */
   1242             case JUNIPER_EXT_TLV_IFL_UNIT:
   1243             case JUNIPER_EXT_TLV_IFD_IDX:
   1244             default:
   1245                 if (tlv_value != -1) {
   1246                     if (ndo->ndo_vflag > 1)
   1247                         ND_PRINT((ndo, "%u", tlv_value));
   1248                 }
   1249                 break;
   1250             }
   1251 
   1252             tptr+=tlv_len;
   1253             jnx_ext_len -= tlv_len+JUNIPER_EXT_TLV_OVERHEAD;
   1254         }
   1255 
   1256         if (ndo->ndo_vflag > 1)
   1257             ND_PRINT((ndo, "\n\t-----original packet-----\n\t"));
   1258     }
   1259 
   1260     if ((l2info->flags & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
   1261         if (ndo->ndo_eflag)
   1262             ND_PRINT((ndo, "no-L2-hdr, "));
   1263 
   1264         /* there is no link-layer present -
   1265          * perform the v4/v6 heuristics
   1266          * to figure out what it is
   1267          */
   1268         ND_TCHECK2(p[jnx_header_len + 4], 1);
   1269         if (ip_heuristic_guess(ndo, p + jnx_header_len + 4,
   1270                                l2info->length - (jnx_header_len + 4)) == 0)
   1271             ND_PRINT((ndo, "no IP-hdr found!"));
   1272 
   1273         l2info->header_len=jnx_header_len+4;
   1274         return 0; /* stop parsing the output further */
   1275 
   1276     }
   1277     l2info->header_len = jnx_header_len;
   1278     p+=l2info->header_len;
   1279     l2info->length -= l2info->header_len;
   1280     l2info->caplen -= l2info->header_len;
   1281 
   1282     /* search through the cookie table and copy values matching for our PIC type */
   1283     while (lp->s != NULL) {
   1284         if (lp->pictype == l2info->pictype) {
   1285 
   1286             l2info->cookie_len += lp->cookie_len;
   1287 
   1288             switch (p[0]) {
   1289             case LS_COOKIE_ID:
   1290                 l2info->cookie_type = LS_COOKIE_ID;
   1291                 l2info->cookie_len += 2;
   1292                 break;
   1293             case AS_COOKIE_ID:
   1294                 l2info->cookie_type = AS_COOKIE_ID;
   1295                 l2info->cookie_len = 8;
   1296                 break;
   1297 
   1298             default:
   1299                 l2info->bundle = l2info->cookie[0];
   1300                 break;
   1301             }
   1302 
   1303 
   1304 #ifdef DLT_JUNIPER_MFR
   1305             /* MFR child links don't carry cookies */
   1306             if (l2info->pictype == DLT_JUNIPER_MFR &&
   1307                 (p[0] & MFR_BE_MASK) == MFR_BE_MASK) {
   1308                 l2info->cookie_len = 0;
   1309             }
   1310 #endif
   1311 
   1312             l2info->header_len += l2info->cookie_len;
   1313             l2info->length -= l2info->cookie_len;
   1314             l2info->caplen -= l2info->cookie_len;
   1315 
   1316             if (ndo->ndo_eflag)
   1317                 ND_PRINT((ndo, "%s-PIC, cookie-len %u",
   1318                        lp->s,
   1319                        l2info->cookie_len));
   1320 
   1321             if (l2info->cookie_len > 0) {
   1322                 ND_TCHECK2(p[0], l2info->cookie_len);
   1323                 if (ndo->ndo_eflag)
   1324                     ND_PRINT((ndo, ", cookie 0x"));
   1325                 for (idx = 0; idx < l2info->cookie_len; idx++) {
   1326                     l2info->cookie[idx] = p[idx]; /* copy cookie data */
   1327                     if (ndo->ndo_eflag) ND_PRINT((ndo, "%02x", p[idx]));
   1328                 }
   1329             }
   1330 
   1331             if (ndo->ndo_eflag) ND_PRINT((ndo, ": ")); /* print demarc b/w L2/L3*/
   1332 
   1333 
   1334             l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len);
   1335             break;
   1336         }
   1337         ++lp;
   1338     }
   1339     p+=l2info->cookie_len;
   1340 
   1341     /* DLT_ specific parsing */
   1342     switch(l2info->pictype) {
   1343 #ifdef DLT_JUNIPER_MLPPP
   1344     case DLT_JUNIPER_MLPPP:
   1345         switch (l2info->cookie_type) {
   1346         case LS_COOKIE_ID:
   1347             l2info->bundle = l2info->cookie[1];
   1348             break;
   1349         case AS_COOKIE_ID:
   1350             l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
   1351             l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
   1352             break;
   1353         default:
   1354             l2info->bundle = l2info->cookie[0];
   1355             break;
   1356         }
   1357         break;
   1358 #endif
   1359 #ifdef DLT_JUNIPER_MLFR
   1360     case DLT_JUNIPER_MLFR:
   1361         switch (l2info->cookie_type) {
   1362         case LS_COOKIE_ID:
   1363             l2info->bundle = l2info->cookie[1];
   1364             l2info->proto = EXTRACT_16BITS(p);
   1365             l2info->header_len += 2;
   1366             l2info->length -= 2;
   1367             l2info->caplen -= 2;
   1368             break;
   1369         case AS_COOKIE_ID:
   1370             l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
   1371             l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
   1372             break;
   1373         default:
   1374             l2info->bundle = l2info->cookie[0];
   1375             l2info->header_len += 2;
   1376             l2info->length -= 2;
   1377             l2info->caplen -= 2;
   1378             break;
   1379         }
   1380         break;
   1381 #endif
   1382 #ifdef DLT_JUNIPER_MFR
   1383     case DLT_JUNIPER_MFR:
   1384         switch (l2info->cookie_type) {
   1385         case LS_COOKIE_ID:
   1386             l2info->bundle = l2info->cookie[1];
   1387             l2info->proto = EXTRACT_16BITS(p);
   1388             l2info->header_len += 2;
   1389             l2info->length -= 2;
   1390             l2info->caplen -= 2;
   1391             break;
   1392         case AS_COOKIE_ID:
   1393             l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
   1394             l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
   1395             break;
   1396         default:
   1397             l2info->bundle = l2info->cookie[0];
   1398             break;
   1399         }
   1400         break;
   1401 #endif
   1402 #ifdef DLT_JUNIPER_ATM2
   1403     case DLT_JUNIPER_ATM2:
   1404         ND_TCHECK2(p[0], 4);
   1405         /* ATM cell relay control word present ? */
   1406         if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK) {
   1407             control_word = EXTRACT_32BITS(p);
   1408             /* some control word heuristics */
   1409             switch(control_word) {
   1410             case 0: /* zero control word */
   1411             case 0x08000000: /* < JUNOS 7.4 control-word */
   1412             case 0x08380000: /* cntl word plus cell length (56) >= JUNOS 7.4*/
   1413                 l2info->header_len += 4;
   1414                 break;
   1415             default:
   1416                 break;
   1417             }
   1418 
   1419             if (ndo->ndo_eflag)
   1420                 ND_PRINT((ndo, "control-word 0x%08x ", control_word));
   1421         }
   1422         break;
   1423 #endif
   1424 #ifdef DLT_JUNIPER_GGSN
   1425     case DLT_JUNIPER_GGSN:
   1426         break;
   1427 #endif
   1428 #ifdef DLT_JUNIPER_ATM1
   1429     case DLT_JUNIPER_ATM1:
   1430         break;
   1431 #endif
   1432 #ifdef DLT_JUNIPER_PPP
   1433     case DLT_JUNIPER_PPP:
   1434         break;
   1435 #endif
   1436 #ifdef DLT_JUNIPER_CHDLC
   1437     case DLT_JUNIPER_CHDLC:
   1438         break;
   1439 #endif
   1440 #ifdef DLT_JUNIPER_ETHER
   1441     case DLT_JUNIPER_ETHER:
   1442         break;
   1443 #endif
   1444 #ifdef DLT_JUNIPER_FRELAY
   1445     case DLT_JUNIPER_FRELAY:
   1446         break;
   1447 #endif
   1448 
   1449     default:
   1450         ND_PRINT((ndo, "Unknown Juniper DLT_ type %u: ", l2info->pictype));
   1451         break;
   1452     }
   1453 
   1454     if (ndo->ndo_eflag > 1)
   1455         ND_PRINT((ndo, "hlen %u, proto 0x%04x, ", l2info->header_len, l2info->proto));
   1456 
   1457     return 1; /* everything went ok so far. continue parsing */
   1458  trunc:
   1459     ND_PRINT((ndo, "[|juniper_hdr], length %u", h->len));
   1460     return 0;
   1461 }
   1462 
   1463 
   1464 /*
   1465  * Local Variables:
   1466  * c-style: whitesmith
   1467  * c-basic-offset: 4
   1468  * End:
   1469  */
   1470