2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that: (1) source code
4 * distributions retain the above copyright notice and this paragraph
5 * in its entirety, and (2) distributions including binary code include
6 * the above copyright notice and this paragraph in its entirety in
7 * the documentation or other materials provided with the distribution.
8 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9 * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
10 * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11 * FOR A PARTICULAR PURPOSE.
13 * Original code by Hannes Gredler (hannes@juniper.net)
17 static const char rcsid
[] _U_
=
18 "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.8.2.5 2005-05-10 10:47:47 hannes Exp $ (LBL)";
25 #include <tcpdump-stdinc.h>
30 #include "interface.h"
36 #define JUNIPER_BPF_OUT 0 /* Outgoing packet */
37 #define JUNIPER_BPF_IN 1 /* Incoming packet */
38 #define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */
39 #define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */
40 #define JUNIPER_MGC_NUMBER 0x4d4743 /* = "MGC" */
42 static struct tok juniper_direction_values
[] = {
43 { JUNIPER_BPF_IN
, "In"},
44 { JUNIPER_BPF_OUT
, "Out"},
48 /* FIXME change enums to real DLT_s */
63 struct juniper_cookie_table_t
{
64 u_int32_t pictype
; /* pic type */
65 u_int8_t cookie_len
; /* cookie len */
66 const char *s
; /* pic name */
69 static struct juniper_cookie_table_t juniper_cookie_table
[] = {
70 { JUNIPER_ATM1
, 4, "ATM1"},
71 { JUNIPER_ATM2
, 8, "ATM2"},
72 { JUNIPER_MLPPP
, 2, "MLPPP"},
73 { JUNIPER_MLFR
, 2, "MLFR"},
74 { JUNIPER_MFR
, 4, "MFR"},
75 { JUNIPER_PPPOE
, 0, "PPPoE"},
78 struct juniper_l2info_t
{
91 #define LS_COOKIE_ID 0x54
92 #define LS_MLFR_COOKIE_LEN 4
93 #define ML_MLFR_COOKIE_LEN 2
94 #define LS_MFR_COOKIE_LEN 6
95 #define ATM1_COOKIE_LEN 4
96 #define ATM2_COOKIE_LEN 8
98 #define ATM2_PKT_TYPE_MASK 0x70
99 #define ATM2_GAP_COUNT_MASK 0x3F
101 int ip_heuristic_guess(register const u_char
*, u_int
);
102 int juniper_ppp_heuristic_guess(register const u_char
*, u_int
);
103 static int juniper_parse_header (const u_char
*, const struct pcap_pkthdr
*, struct juniper_l2info_t
*);
106 juniper_pppoe_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
108 struct juniper_l2info_t l2info
;
110 l2info
.pictype
= JUNIPER_PPPOE
;
111 if(juniper_parse_header(p
, h
, &l2info
) == 0)
112 return l2info
.header_len
;
114 p
+=l2info
.header_len
;
115 /* this DLT contains nothing but raw ethernet frames */
116 ether_print(p
, l2info
.length
, l2info
.caplen
);
117 return l2info
.header_len
;
122 juniper_mlppp_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
124 struct juniper_l2info_t l2info
;
126 l2info
.pictype
= JUNIPER_MLPPP
;
127 if(juniper_parse_header(p
, h
, &l2info
) == 0)
128 return l2info
.header_len
;
130 /* suppress Bundle-ID if frame was captured on a child-link
131 * best indicator if the cookie looks like a proto */
133 EXTRACT_16BITS(&l2info
.cookie
) != PPP_OSI
&&
134 EXTRACT_16BITS(&l2info
.cookie
) != (PPP_ADDRESS
<< 8 | PPP_CONTROL
))
135 printf(", Bundle-ID %u: ",l2info
.bundle
);
137 p
+=l2info
.header_len
;
139 switch (EXTRACT_16BITS(&l2info
.cookie
)) {
141 ppp_print(p
-2,l2info
.length
+2);
143 case (PPP_ADDRESS
<< 8 | PPP_CONTROL
): /* fall through */
145 ppp_print(p
,l2info
.length
);
149 return l2info
.header_len
;
154 juniper_mfr_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
156 struct juniper_l2info_t l2info
;
158 l2info
.pictype
= JUNIPER_MFR
;
159 if(juniper_parse_header(p
, h
, &l2info
) == 0)
160 return l2info
.header_len
;
162 p
+=l2info
.header_len
;
163 /* suppress Bundle-ID if frame was captured on a child-link */
164 if (eflag
&& EXTRACT_32BITS(l2info
.cookie
) != 1) printf("Bundle-ID %u, ",l2info
.bundle
);
165 switch (l2info
.proto
) {
166 case (LLCSAP_ISONS
<<8 | LLCSAP_ISONS
):
167 isoclns_print(p
+1, l2info
.length
-1, l2info
.caplen
-1);
169 case (LLC_UI
<<8 | NLPID_Q933
):
170 case (LLC_UI
<<8 | NLPID_IP
):
171 case (LLC_UI
<<8 | NLPID_IP6
):
172 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
173 isoclns_print(p
-1, l2info
.length
+1, l2info
.caplen
+1);
176 printf("unknown protocol 0x%04x, length %u",l2info
.proto
, l2info
.length
);
179 return l2info
.header_len
;
183 juniper_mlfr_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
185 struct juniper_l2info_t l2info
;
187 l2info
.pictype
= JUNIPER_MLFR
;
188 if(juniper_parse_header(p
, h
, &l2info
) == 0)
189 return l2info
.header_len
;
191 p
+=l2info
.header_len
;
193 /* suppress Bundle-ID if frame was captured on a child-link */
194 if (eflag
&& EXTRACT_32BITS(l2info
.cookie
) != 1) printf("Bundle-ID %u, ",l2info
.bundle
);
195 switch (l2info
.proto
) {
198 isoclns_print(p
, l2info
.length
, l2info
.caplen
);
200 case (LLC_UI
<<8 | NLPID_Q933
):
201 case (LLC_UI
<<8 | NLPID_IP
):
202 case (LLC_UI
<<8 | NLPID_IP6
):
203 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
204 isoclns_print(p
-1, l2info
.length
+1, l2info
.caplen
+1);
207 printf("unknown protocol 0x%04x, length %u",l2info
.proto
, l2info
.length
);
210 return l2info
.header_len
;
214 * ATM1 PIC cookie format
216 * +-----+-------------------------+-------------------------------+
217 * |fmtid| vc index | channel ID |
218 * +-----+-------------------------+-------------------------------+
222 juniper_atm1_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
224 u_int16_t extracted_ethertype
;
226 struct juniper_l2info_t l2info
;
228 l2info
.pictype
= JUNIPER_ATM1
;
229 if(juniper_parse_header(p
, h
, &l2info
) == 0)
230 return l2info
.header_len
;
232 p
+=l2info
.header_len
;
234 if (l2info
.cookie
[0] == 0x80) { /* OAM cell ? */
235 oam_print(p
,l2info
.length
);
236 return l2info
.header_len
;
239 if (EXTRACT_24BITS(p
) == 0xfefe03 || /* NLPID encaps ? */
240 EXTRACT_24BITS(p
) == 0xaaaa03) { /* SNAP encaps ? */
242 if (llc_print(p
, l2info
.length
, l2info
.caplen
, NULL
, NULL
,
243 &extracted_ethertype
) != 0)
244 return l2info
.header_len
;
247 if (p
[0] == 0x03) { /* Cisco style NLPID encaps ? */
248 isoclns_print(p
+ 1, l2info
.length
- 1, l2info
.caplen
- 1);
249 /* FIXME check if frame was recognized */
250 return l2info
.header_len
;
253 if(ip_heuristic_guess(p
, l2info
.length
) != 0) /* last try - vcmux encaps ? */
254 return l2info
.header_len
;
256 return l2info
.header_len
;
260 * ATM2 PIC cookie format
262 * +-------------------------------+---------+---+-----+-----------+
263 * | channel ID | reserv |AAL| CCRQ| gap cnt |
264 * +-------------------------------+---------+---+-----+-----------+
268 juniper_atm2_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
270 u_int16_t extracted_ethertype
;
272 struct juniper_l2info_t l2info
;
274 l2info
.pictype
= JUNIPER_ATM2
;
275 if(juniper_parse_header(p
, h
, &l2info
) == 0)
276 return l2info
.header_len
;
278 p
+=l2info
.header_len
;
280 if (l2info
.cookie
[7] & ATM2_PKT_TYPE_MASK
) { /* OAM cell ? */
281 oam_print(p
,l2info
.length
);
282 return l2info
.header_len
;
285 if (EXTRACT_24BITS(p
) == 0xfefe03 || /* NLPID encaps ? */
286 EXTRACT_24BITS(p
) == 0xaaaa03) { /* SNAP encaps ? */
288 if (llc_print(p
, l2info
.length
, l2info
.caplen
, NULL
, NULL
,
289 &extracted_ethertype
) != 0)
290 return l2info
.header_len
;
293 if (l2info
.direction
!= JUNIPER_BPF_PKT_IN
&& /* ether-over-1483 encaps ? */
294 (EXTRACT_32BITS(l2info
.cookie
) & ATM2_GAP_COUNT_MASK
)) {
295 ether_print(p
, l2info
.length
, l2info
.caplen
);
296 return l2info
.header_len
;
299 if (p
[0] == 0x03) { /* Cisco style NLPID encaps ? */
300 isoclns_print(p
+ 1, l2info
.length
- 1, l2info
.caplen
- 1);
301 /* FIXME check if frame was recognized */
302 return l2info
.header_len
;
305 if(juniper_ppp_heuristic_guess(p
, l2info
.length
) != 0) /* PPPoA vcmux encaps ? */
306 return l2info
.header_len
;
308 if(ip_heuristic_guess(p
, l2info
.length
) != 0) /* last try - vcmux encaps ? */
309 return l2info
.header_len
;
311 return l2info
.header_len
;
315 /* try to guess, based on all PPP protos that are supported in
316 * a juniper router if the payload data is encapsulated using PPP */
318 juniper_ppp_heuristic_guess(register const u_char
*p
, u_int length
) {
320 switch(EXTRACT_16BITS(p
)) {
323 case PPP_MPLS_UCAST
:
324 case PPP_MPLS_MCAST
:
336 ppp_print(p
, length
);
340 return 0; /* did not find a ppp header */
343 return 1; /* we printed a ppp packet */
347 ip_heuristic_guess(register const u_char
*p
, u_int length
) {
361 ip_print(gndo
, p
, length
);
380 ip6_print(p
, length
);
384 return 0; /* did not find a ip header */
387 return 1; /* we printed an v4/v6 packet */
391 juniper_parse_header (const u_char
*p
, const struct pcap_pkthdr
*h
, struct juniper_l2info_t
*l2info
) {
393 struct juniper_cookie_table_t
*lp
= juniper_cookie_table
;
396 l2info
->header_len
= 0;
397 l2info
->cookie_len
= 0;
401 l2info
->length
= h
->len
;
402 l2info
->caplen
= h
->caplen
;
403 l2info
->direction
= p
[3]&JUNIPER_BPF_PKT_IN
;
405 if (EXTRACT_24BITS(p
) != JUNIPER_MGC_NUMBER
) /* magic number found ? */
408 l2info
->header_len
= 4;
410 if (eflag
) /* print direction */
411 printf("%3s ",tok2str(juniper_direction_values
,"---",l2info
->direction
));
413 if ((p
[3] & JUNIPER_BPF_NO_L2
) == JUNIPER_BPF_NO_L2
) {
415 printf("no-L2-hdr, ");
417 /* there is no link-layer present -
418 * perform the v4/v6 heuristics
419 * to figure out what it is
421 if(ip_heuristic_guess(p
+8,l2info
->length
-8) == 0)
422 printf("no IP-hdr found!");
424 l2info
->header_len
+=4;
425 return 0; /* stop parsing the output further */
429 p
+=l2info
->header_len
;
430 l2info
->length
-= l2info
->header_len
;
431 l2info
->caplen
-= l2info
->header_len
;
433 /* search through the cookie table and copy values matching for our PIC type */
434 while (lp
->s
!= NULL
) {
435 if (lp
->pictype
== l2info
->pictype
) {
437 l2info
->cookie_len
= lp
->cookie_len
;
438 l2info
->header_len
+= lp
->cookie_len
;
440 if(p
[0] == LS_COOKIE_ID
) {
441 l2info
->cookie_type
= LS_COOKIE
;
442 l2info
->cookie_len
+= 2;
443 l2info
->header_len
+= 2;
444 l2info
->bundle
= l2info
->cookie
[1];
445 } else l2info
->bundle
= l2info
->cookie
[0];
448 printf("%s-PIC, cookie-len %u",
452 if (l2info
->cookie_len
> 0) {
454 printf(", cookie 0x");
455 for (idx
= 0; idx
< l2info
->cookie_len
; idx
++) {
456 l2info
->cookie
[idx
] = p
[idx
]; /* copy cookie data */
457 if (eflag
) printf("%02x",p
[idx
]);
461 if (eflag
) printf(": "); /* print demarc b/w L2/L3*/
464 l2info
->proto
= EXTRACT_16BITS(p
+l2info
->cookie_len
);
469 p
+=l2info
->cookie_len
;
471 /* DLT_ specific parsing */
472 switch(l2info
->pictype
) {
474 if (l2info
->cookie_type
== LS_COOKIE
) {
475 l2info
->bundle
= l2info
->cookie
[1];
477 l2info
->bundle
= l2info
->cookie
[0];
480 case JUNIPER_MLFR
: /* fall through */
482 if (l2info
->cookie_type
== LS_COOKIE
) {
483 l2info
->bundle
= l2info
->cookie
[1];
485 l2info
->bundle
= l2info
->cookie
[0];
487 l2info
->proto
= EXTRACT_16BITS(p
);
488 l2info
->header_len
+= 2;
500 printf("hlen %u, proto 0x%04x, ",l2info
->header_len
,l2info
->proto
);
502 return 1; /* everything went ok so far. continue parsing */
508 * c-style: whitesmith