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