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.14 2005-05-12 07:10:55 hannes Exp $ (LBL)";
25 #include <tcpdump-stdinc.h>
30 #include "interface.h"
35 #include "ethertype.h"
37 #define JUNIPER_BPF_OUT 0 /* Outgoing packet */
38 #define JUNIPER_BPF_IN 1 /* Incoming packet */
39 #define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */
40 #define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */
41 #define JUNIPER_MGC_NUMBER 0x4d4743 /* = "MGC" */
43 static struct tok juniper_direction_values
[] = {
44 { JUNIPER_BPF_IN
, "In"},
45 { JUNIPER_BPF_OUT
, "Out"},
54 struct juniper_cookie_table_t
{
55 u_int32_t pictype
; /* pic type */
56 u_int8_t cookie_len
; /* cookie len */
57 const char *s
; /* pic name */
60 static struct juniper_cookie_table_t juniper_cookie_table
[] = {
61 { DLT_JUNIPER_ATM1
, 4, "ATM1"},
62 { DLT_JUNIPER_ATM2
, 8, "ATM2"},
63 { DLT_JUNIPER_MLPPP
, 2, "MLPPP"},
64 { DLT_JUNIPER_MLFR
, 2, "MLFR"},
65 { DLT_JUNIPER_MFR
, 4, "MFR"},
66 { DLT_JUNIPER_PPPOE
, 0, "PPPoE"},
67 { DLT_JUNIPER_PPPOE_ATM
, 0, "PPPoE ATM"},
70 struct juniper_l2info_t
{
83 #define LS_COOKIE_ID 0x54
84 #define LS_MLFR_COOKIE_LEN 4
85 #define ML_MLFR_COOKIE_LEN 2
86 #define LS_MFR_COOKIE_LEN 6
87 #define ATM1_COOKIE_LEN 4
88 #define ATM2_COOKIE_LEN 8
90 #define ATM2_PKT_TYPE_MASK 0x70
91 #define ATM2_GAP_COUNT_MASK 0x3F
93 int ip_heuristic_guess(register const u_char
*, u_int
);
94 int juniper_ppp_heuristic_guess(register const u_char
*, u_int
);
95 static int juniper_parse_header (const u_char
*, const struct pcap_pkthdr
*, struct juniper_l2info_t
*);
98 juniper_pppoe_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
100 struct juniper_l2info_t l2info
;
102 l2info
.pictype
= DLT_JUNIPER_PPPOE
;
103 if(juniper_parse_header(p
, h
, &l2info
) == 0)
104 return l2info
.header_len
;
106 p
+=l2info
.header_len
;
107 /* this DLT contains nothing but raw ethernet frames */
108 ether_print(p
, l2info
.length
, l2info
.caplen
);
109 return l2info
.header_len
;
113 juniper_pppoe_atm_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
115 struct juniper_l2info_t l2info
;
116 u_int16_t extracted_ethertype
;
118 l2info
.pictype
= DLT_JUNIPER_PPPOE_ATM
;
119 if(juniper_parse_header(p
, h
, &l2info
) == 0)
120 return l2info
.header_len
;
122 p
+=l2info
.header_len
;
124 extracted_ethertype
= EXTRACT_16BITS(p
);
125 /* this DLT contains nothing but raw PPPoE frames,
126 * prepended with a type field*/
127 if (ether_encap_print(extracted_ethertype
,
129 l2info
.length
-ETHERTYPE_LEN
,
130 l2info
.caplen
-ETHERTYPE_LEN
,
131 &extracted_ethertype
) == 0)
132 /* ether_type not known, probably it wasn't one */
133 printf("unknown ethertype 0x%04x", extracted_ethertype
);
135 return l2info
.header_len
;
139 juniper_mlppp_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
141 struct juniper_l2info_t l2info
;
143 l2info
.pictype
= DLT_JUNIPER_MLPPP
;
144 if(juniper_parse_header(p
, h
, &l2info
) == 0)
145 return l2info
.header_len
;
147 /* suppress Bundle-ID if frame was captured on a child-link
148 * best indicator if the cookie looks like a proto */
150 EXTRACT_16BITS(&l2info
.cookie
) != PPP_OSI
&&
151 EXTRACT_16BITS(&l2info
.cookie
) != (PPP_ADDRESS
<< 8 | PPP_CONTROL
))
152 printf(", Bundle-ID %u: ",l2info
.bundle
);
154 p
+=l2info
.header_len
;
156 switch (EXTRACT_16BITS(&l2info
.cookie
)) {
158 ppp_print(p
-2,l2info
.length
+2);
160 case (PPP_ADDRESS
<< 8 | PPP_CONTROL
): /* fall through */
162 ppp_print(p
,l2info
.length
);
166 return l2info
.header_len
;
171 juniper_mfr_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
173 struct juniper_l2info_t l2info
;
175 l2info
.pictype
= DLT_JUNIPER_MFR
;
176 if(juniper_parse_header(p
, h
, &l2info
) == 0)
177 return l2info
.header_len
;
179 p
+=l2info
.header_len
;
180 /* suppress Bundle-ID if frame was captured on a child-link */
181 if (eflag
&& EXTRACT_32BITS(l2info
.cookie
) != 1) printf("Bundle-ID %u, ",l2info
.bundle
);
182 switch (l2info
.proto
) {
183 case (LLCSAP_ISONS
<<8 | LLCSAP_ISONS
):
184 isoclns_print(p
+1, l2info
.length
-1, l2info
.caplen
-1);
186 case (LLC_UI
<<8 | NLPID_Q933
):
187 case (LLC_UI
<<8 | NLPID_IP
):
188 case (LLC_UI
<<8 | NLPID_IP6
):
189 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
190 isoclns_print(p
-1, l2info
.length
+1, l2info
.caplen
+1);
193 printf("unknown protocol 0x%04x, length %u",l2info
.proto
, l2info
.length
);
196 return l2info
.header_len
;
200 juniper_mlfr_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
202 struct juniper_l2info_t l2info
;
204 l2info
.pictype
= DLT_JUNIPER_MLFR
;
205 if(juniper_parse_header(p
, h
, &l2info
) == 0)
206 return l2info
.header_len
;
208 p
+=l2info
.header_len
;
210 /* suppress Bundle-ID if frame was captured on a child-link */
211 if (eflag
&& EXTRACT_32BITS(l2info
.cookie
) != 1) printf("Bundle-ID %u, ",l2info
.bundle
);
212 switch (l2info
.proto
) {
215 isoclns_print(p
, l2info
.length
, l2info
.caplen
);
217 case (LLC_UI
<<8 | NLPID_Q933
):
218 case (LLC_UI
<<8 | NLPID_IP
):
219 case (LLC_UI
<<8 | NLPID_IP6
):
220 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
221 isoclns_print(p
-1, l2info
.length
+1, l2info
.caplen
+1);
224 printf("unknown protocol 0x%04x, length %u",l2info
.proto
, l2info
.length
);
227 return l2info
.header_len
;
231 * ATM1 PIC cookie format
233 * +-----+-------------------------+-------------------------------+
234 * |fmtid| vc index | channel ID |
235 * +-----+-------------------------+-------------------------------+
239 juniper_atm1_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
241 u_int16_t extracted_ethertype
;
243 struct juniper_l2info_t l2info
;
245 l2info
.pictype
= DLT_JUNIPER_ATM1
;
246 if(juniper_parse_header(p
, h
, &l2info
) == 0)
247 return l2info
.header_len
;
249 p
+=l2info
.header_len
;
251 if (l2info
.cookie
[0] == 0x80) { /* OAM cell ? */
252 oam_print(p
,l2info
.length
);
253 return l2info
.header_len
;
256 if (EXTRACT_24BITS(p
) == 0xfefe03 || /* NLPID encaps ? */
257 EXTRACT_24BITS(p
) == 0xaaaa03) { /* SNAP encaps ? */
259 if (llc_print(p
, l2info
.length
, l2info
.caplen
, NULL
, NULL
,
260 &extracted_ethertype
) != 0)
261 return l2info
.header_len
;
264 if (p
[0] == 0x03) { /* Cisco style NLPID encaps ? */
265 isoclns_print(p
+ 1, l2info
.length
- 1, l2info
.caplen
- 1);
266 /* FIXME check if frame was recognized */
267 return l2info
.header_len
;
270 if(ip_heuristic_guess(p
, l2info
.length
) != 0) /* last try - vcmux encaps ? */
271 return l2info
.header_len
;
273 return l2info
.header_len
;
277 * ATM2 PIC cookie format
279 * +-------------------------------+---------+---+-----+-----------+
280 * | channel ID | reserv |AAL| CCRQ| gap cnt |
281 * +-------------------------------+---------+---+-----+-----------+
285 juniper_atm2_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
287 u_int16_t extracted_ethertype
;
289 struct juniper_l2info_t l2info
;
291 l2info
.pictype
= DLT_JUNIPER_ATM2
;
292 if(juniper_parse_header(p
, h
, &l2info
) == 0)
293 return l2info
.header_len
;
295 p
+=l2info
.header_len
;
297 if (l2info
.cookie
[7] & ATM2_PKT_TYPE_MASK
) { /* OAM cell ? */
298 oam_print(p
,l2info
.length
);
299 return l2info
.header_len
;
302 if (EXTRACT_24BITS(p
) == 0xfefe03 || /* NLPID encaps ? */
303 EXTRACT_24BITS(p
) == 0xaaaa03) { /* SNAP encaps ? */
305 if (llc_print(p
, l2info
.length
, l2info
.caplen
, NULL
, NULL
,
306 &extracted_ethertype
) != 0)
307 return l2info
.header_len
;
310 if (l2info
.direction
!= JUNIPER_BPF_PKT_IN
&& /* ether-over-1483 encaps ? */
311 (EXTRACT_32BITS(l2info
.cookie
) & ATM2_GAP_COUNT_MASK
)) {
312 ether_print(p
, l2info
.length
, l2info
.caplen
);
313 return l2info
.header_len
;
316 if (p
[0] == 0x03) { /* Cisco style NLPID encaps ? */
317 isoclns_print(p
+ 1, l2info
.length
- 1, l2info
.caplen
- 1);
318 /* FIXME check if frame was recognized */
319 return l2info
.header_len
;
322 if(juniper_ppp_heuristic_guess(p
, l2info
.length
) != 0) /* PPPoA vcmux encaps ? */
323 return l2info
.header_len
;
325 if(ip_heuristic_guess(p
, l2info
.length
) != 0) /* last try - vcmux encaps ? */
326 return l2info
.header_len
;
328 return l2info
.header_len
;
332 /* try to guess, based on all PPP protos that are supported in
333 * a juniper router if the payload data is encapsulated using PPP */
335 juniper_ppp_heuristic_guess(register const u_char
*p
, u_int length
) {
337 switch(EXTRACT_16BITS(p
)) {
340 case PPP_MPLS_UCAST
:
341 case PPP_MPLS_MCAST
:
353 ppp_print(p
, length
);
357 return 0; /* did not find a ppp header */
360 return 1; /* we printed a ppp packet */
364 ip_heuristic_guess(register const u_char
*p
, u_int length
) {
378 ip_print(gndo
, p
, length
);
397 ip6_print(p
, length
);
401 return 0; /* did not find a ip header */
404 return 1; /* we printed an v4/v6 packet */
408 juniper_parse_header (const u_char
*p
, const struct pcap_pkthdr
*h
, struct juniper_l2info_t
*l2info
) {
410 struct juniper_cookie_table_t
*lp
= juniper_cookie_table
;
413 l2info
->header_len
= 0;
414 l2info
->cookie_len
= 0;
418 l2info
->length
= h
->len
;
419 l2info
->caplen
= h
->caplen
;
420 l2info
->direction
= p
[3]&JUNIPER_BPF_PKT_IN
;
422 if (EXTRACT_24BITS(p
) != JUNIPER_MGC_NUMBER
) /* magic number found ? */
425 l2info
->header_len
= 4;
427 if (eflag
) /* print direction */
428 printf("%3s ",tok2str(juniper_direction_values
,"---",l2info
->direction
));
430 if ((p
[3] & JUNIPER_BPF_NO_L2
) == JUNIPER_BPF_NO_L2
) {
432 printf("no-L2-hdr, ");
434 /* there is no link-layer present -
435 * perform the v4/v6 heuristics
436 * to figure out what it is
438 if(ip_heuristic_guess(p
+8,l2info
->length
-8) == 0)
439 printf("no IP-hdr found!");
441 l2info
->header_len
+=4;
442 return 0; /* stop parsing the output further */
446 p
+=l2info
->header_len
;
447 l2info
->length
-= l2info
->header_len
;
448 l2info
->caplen
-= l2info
->header_len
;
450 /* search through the cookie table and copy values matching for our PIC type */
451 while (lp
->s
!= NULL
) {
452 if (lp
->pictype
== l2info
->pictype
) {
454 l2info
->cookie_len
= lp
->cookie_len
;
455 l2info
->header_len
+= lp
->cookie_len
;
457 if(p
[0] == LS_COOKIE_ID
) {
458 l2info
->cookie_type
= LS_COOKIE
;
459 l2info
->cookie_len
+= 2;
460 l2info
->header_len
+= 2;
461 l2info
->bundle
= l2info
->cookie
[1];
462 } else l2info
->bundle
= l2info
->cookie
[0];
465 printf("%s-PIC, cookie-len %u",
469 if (l2info
->cookie_len
> 0) {
471 printf(", cookie 0x");
472 for (idx
= 0; idx
< l2info
->cookie_len
; idx
++) {
473 l2info
->cookie
[idx
] = p
[idx
]; /* copy cookie data */
474 if (eflag
) printf("%02x",p
[idx
]);
478 if (eflag
) printf(": "); /* print demarc b/w L2/L3*/
481 l2info
->proto
= EXTRACT_16BITS(p
+l2info
->cookie_len
);
486 p
+=l2info
->cookie_len
;
488 /* DLT_ specific parsing */
489 switch(l2info
->pictype
) {
490 case DLT_JUNIPER_MLPPP
:
491 if (l2info
->cookie_type
== LS_COOKIE
) {
492 l2info
->bundle
= l2info
->cookie
[1];
494 l2info
->bundle
= l2info
->cookie
[0];
497 case DLT_JUNIPER_MLFR
: /* fall through */
498 case DLT_JUNIPER_MFR
:
499 if (l2info
->cookie_type
== LS_COOKIE
) {
500 l2info
->bundle
= l2info
->cookie
[1];
502 l2info
->bundle
= l2info
->cookie
[0];
504 l2info
->proto
= EXTRACT_16BITS(p
);
505 l2info
->header_len
+= 2;
509 case DLT_JUNIPER_ATM2
:
510 case DLT_JUNIPER_ATM1
:
517 printf("hlen %u, proto 0x%04x, ",l2info
->header_len
,l2info
->proto
);
519 return 1; /* everything went ok so far. continue parsing */
525 * c-style: whitesmith