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