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@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
64static 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
73static 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 */
80enum {
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
94static 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
106static 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
176static 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
299static 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
364struct 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
370static 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
407struct 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
438static 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
445static int ip_heuristic_guess(netdissect_options *, register const u_char *, u_int);
446static int juniper_ppp_heuristic_guess(netdissect_options *, register const u_char *, u_int);
447static int juniper_parse_header(netdissect_options *, const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
448
449#ifdef DLT_JUNIPER_GGSN
450u_int
451juniper_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
496u_int
497juniper_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
568u_int
569juniper_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
602u_int
603juniper_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
637u_int
638juniper_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
655u_int
656juniper_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
673u_int
674juniper_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
691u_int
692juniper_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
709u_int
710juniper_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
727u_int
728juniper_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
755u_int
756juniper_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
815u_int
816juniper_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
876u_int
877juniper_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
919u_int
920juniper_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
968u_int
969juniper_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 */
1020static int
1021juniper_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
1050static int
1051ip_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
1093static int
1094juniper_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
1140static int
1141juniper_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