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