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.11 2005-04-25 18:53:27 guy 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 */
62 struct juniper_cookie_table_t
{
63 u_int32_t pictype
; /* pic type */
64 u_int8_t cookie_len
; /* cookie len */
65 const char *s
; /* pic name */
68 static struct juniper_cookie_table_t juniper_cookie_table
[] = {
69 { JUNIPER_ATM1
, 4, "ATM1"},
70 { JUNIPER_ATM2
, 8, "ATM2"},
71 { JUNIPER_MLPPP
, 2, "MLPPP"},
72 { JUNIPER_MLFR
, 2, "MLFR"},
73 { JUNIPER_MFR
, 4, "MFR"},
76 struct juniper_l2info_t
{
89 #define LS_COOKIE_ID 0x54
90 #define LS_MLFR_COOKIE_LEN 4
91 #define ML_MLFR_COOKIE_LEN 2
92 #define LS_MFR_COOKIE_LEN 6
93 #define ATM1_COOKIE_LEN 4
94 #define ATM2_COOKIE_LEN 8
96 #define ATM2_PKT_TYPE_MASK 0x70
97 #define ATM2_GAP_COUNT_MASK 0x3F
99 int ip_heuristic_guess(register const u_char
*, u_int
);
100 int juniper_ppp_heuristic_guess(register const u_char
*, u_int
);
101 static int juniper_parse_header (const u_char
*, const struct pcap_pkthdr
*, struct juniper_l2info_t
*);
104 juniper_mlppp_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
106 struct juniper_l2info_t l2info
;
108 l2info
.pictype
= JUNIPER_MLPPP
;
109 if(juniper_parse_header(p
, h
, &l2info
) == 0)
110 return l2info
.header_len
;
112 /* suppress Bundle-ID if frame was captured on a child-link
113 * best indicator if the cookie looks like a proto */
115 EXTRACT_16BITS(&l2info
.cookie
) != PPP_OSI
&&
116 EXTRACT_16BITS(&l2info
.cookie
) != (PPP_ADDRESS
<< 8 | PPP_CONTROL
))
117 printf(", Bundle-ID %u: ",l2info
.bundle
);
119 p
+=l2info
.header_len
;
121 switch (EXTRACT_16BITS(&l2info
.cookie
)) {
123 ppp_print(p
-2,l2info
.length
+2);
125 case (PPP_ADDRESS
<< 8 | PPP_CONTROL
): /* fall through */
127 ppp_print(p
,l2info
.length
);
131 return l2info
.header_len
;
136 juniper_mfr_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
138 struct juniper_l2info_t l2info
;
140 l2info
.pictype
= JUNIPER_MFR
;
141 if(juniper_parse_header(p
, h
, &l2info
) == 0)
142 return l2info
.header_len
;
144 p
+=l2info
.header_len
;
145 /* suppress Bundle-ID if frame was captured on a child-link */
146 if (eflag
&& EXTRACT_32BITS(l2info
.cookie
) != 1) printf("Bundle-ID %u, ",l2info
.bundle
);
147 switch (l2info
.proto
) {
148 case (LLCSAP_ISONS
<<8 | LLCSAP_ISONS
):
149 isoclns_print(p
+1, l2info
.length
-1, l2info
.caplen
-1);
151 case (LLC_UI
<<8 | NLPID_Q933
):
152 case (LLC_UI
<<8 | NLPID_IP
):
153 case (LLC_UI
<<8 | NLPID_IP6
):
154 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
155 isoclns_print(p
-1, l2info
.length
+1, l2info
.caplen
+1);
158 printf("unknown protocol 0x%04x, length %u",l2info
.proto
, l2info
.length
);
161 return l2info
.header_len
;
165 juniper_mlfr_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
167 struct juniper_l2info_t l2info
;
169 l2info
.pictype
= JUNIPER_MLFR
;
170 if(juniper_parse_header(p
, h
, &l2info
) == 0)
171 return l2info
.header_len
;
173 p
+=l2info
.header_len
;
175 /* suppress Bundle-ID if frame was captured on a child-link */
176 if (eflag
&& EXTRACT_32BITS(l2info
.cookie
) != 1) printf("Bundle-ID %u, ",l2info
.bundle
);
177 switch (l2info
.proto
) {
180 isoclns_print(p
, l2info
.length
, l2info
.caplen
);
182 case (LLC_UI
<<8 | NLPID_Q933
):
183 case (LLC_UI
<<8 | NLPID_IP
):
184 case (LLC_UI
<<8 | NLPID_IP6
):
185 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
186 isoclns_print(p
-1, l2info
.length
+1, l2info
.caplen
+1);
189 printf("unknown protocol 0x%04x, length %u",l2info
.proto
, l2info
.length
);
192 return l2info
.header_len
;
196 * ATM1 PIC cookie format
198 * +-----+-------------------------+-------------------------------+
199 * |fmtid| vc index | channel ID |
200 * +-----+-------------------------+-------------------------------+
204 juniper_atm1_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
206 u_int16_t extracted_ethertype
;
208 struct juniper_l2info_t l2info
;
210 l2info
.pictype
= JUNIPER_ATM1
;
211 if(juniper_parse_header(p
, h
, &l2info
) == 0)
212 return l2info
.header_len
;
214 p
+=l2info
.header_len
;
216 if (l2info
.cookie
[0] == 0x80) { /* OAM cell ? */
217 oam_print(p
,l2info
.length
);
218 return l2info
.header_len
;
221 if (EXTRACT_24BITS(p
) == 0xfefe03 || /* NLPID encaps ? */
222 EXTRACT_24BITS(p
) == 0xaaaa03) { /* SNAP encaps ? */
224 if (llc_print(p
, l2info
.length
, l2info
.caplen
, NULL
, NULL
,
225 &extracted_ethertype
) != 0)
226 return l2info
.header_len
;
229 if (p
[0] == 0x03) { /* Cisco style NLPID encaps ? */
230 isoclns_print(p
+ 1, l2info
.length
- 1, l2info
.caplen
- 1);
231 /* FIXME check if frame was recognized */
232 return l2info
.header_len
;
235 if(ip_heuristic_guess(p
, l2info
.length
) != 0) /* last try - vcmux encaps ? */
236 return l2info
.header_len
;
238 return l2info
.header_len
;
242 * ATM2 PIC cookie format
244 * +-------------------------------+---------+---+-----+-----------+
245 * | channel ID | reserv |AAL| CCRQ| gap cnt |
246 * +-------------------------------+---------+---+-----+-----------+
250 juniper_atm2_print(const struct pcap_pkthdr
*h
, register const u_char
*p
)
252 u_int16_t extracted_ethertype
;
254 struct juniper_l2info_t l2info
;
256 l2info
.pictype
= JUNIPER_ATM2
;
257 if(juniper_parse_header(p
, h
, &l2info
) == 0)
258 return l2info
.header_len
;
260 p
+=l2info
.header_len
;
262 if (l2info
.cookie
[7] & ATM2_PKT_TYPE_MASK
) { /* OAM cell ? */
263 oam_print(p
,l2info
.length
);
264 return l2info
.header_len
;
267 if (EXTRACT_24BITS(p
) == 0xfefe03 || /* NLPID encaps ? */
268 EXTRACT_24BITS(p
) == 0xaaaa03) { /* SNAP encaps ? */
270 if (llc_print(p
, l2info
.length
, l2info
.caplen
, NULL
, NULL
,
271 &extracted_ethertype
) != 0)
272 return l2info
.header_len
;
275 if (l2info
.direction
!= JUNIPER_BPF_PKT_IN
&& /* ether-over-1483 encaps ? */
276 (EXTRACT_32BITS(l2info
.cookie
) & ATM2_GAP_COUNT_MASK
)) {
277 ether_print(p
, l2info
.length
, l2info
.caplen
);
278 return l2info
.header_len
;
281 if (p
[0] == 0x03) { /* Cisco style NLPID encaps ? */
282 isoclns_print(p
+ 1, l2info
.length
- 1, l2info
.caplen
- 1);
283 /* FIXME check if frame was recognized */
284 return l2info
.header_len
;
287 if(juniper_ppp_heuristic_guess(p
, l2info
.length
) != 0) /* PPPoA vcmux encaps ? */
288 return l2info
.header_len
;
290 if(ip_heuristic_guess(p
, l2info
.length
) != 0) /* last try - vcmux encaps ? */
291 return l2info
.header_len
;
293 return l2info
.header_len
;
297 /* try to guess, based on all PPP protos that are supported in
298 * a juniper router if the payload data is encapsulated using PPP */
300 juniper_ppp_heuristic_guess(register const u_char
*p
, u_int length
) {
302 switch(EXTRACT_16BITS(p
)) {
305 case PPP_MPLS_UCAST
:
306 case PPP_MPLS_MCAST
:
318 ppp_print(p
, length
);
322 return 0; /* did not find a ppp header */
325 return 1; /* we printed a ppp packet */
329 ip_heuristic_guess(register const u_char
*p
, u_int length
) {
343 ip_print(gndo
, p
, length
);
362 ip6_print(p
, length
);
366 return 0; /* did not find a ip header */
369 return 1; /* we printed an v4/v6 packet */
373 juniper_parse_header (const u_char
*p
, const struct pcap_pkthdr
*h
, struct juniper_l2info_t
*l2info
) {
375 struct juniper_cookie_table_t
*lp
= juniper_cookie_table
;
378 l2info
->header_len
= 0;
379 l2info
->cookie_len
= 0;
383 l2info
->length
= h
->len
;
384 l2info
->caplen
= h
->caplen
;
385 l2info
->direction
= p
[3]&JUNIPER_BPF_PKT_IN
;
387 if (EXTRACT_24BITS(p
) != JUNIPER_MGC_NUMBER
) /* magic number found ? */
390 l2info
->header_len
= 4;
392 if (eflag
) /* print direction */
393 printf("%3s ",tok2str(juniper_direction_values
,"---",l2info
->direction
));
395 if ((p
[3] & JUNIPER_BPF_NO_L2
) == JUNIPER_BPF_NO_L2
) {
397 printf("no-L2-hdr, ");
399 /* there is no link-layer present -
400 * perform the v4/v6 heuristics
401 * to figure out what it is
403 if(ip_heuristic_guess(p
+8,l2info
->length
-8) == 0)
404 printf("no IP-hdr found!");
406 l2info
->header_len
+=4;
407 return 0; /* stop parsing the output further */
411 p
+=l2info
->header_len
;
412 l2info
->length
-= l2info
->header_len
;
413 l2info
->caplen
-= l2info
->header_len
;
415 /* search through the cookie table and copy values matching for our PIC type */
416 while (lp
->s
!= NULL
) {
417 if (lp
->pictype
== l2info
->pictype
) {
419 l2info
->cookie_len
= lp
->cookie_len
;
420 l2info
->header_len
+= lp
->cookie_len
;
422 if(p
[0] == LS_COOKIE_ID
) {
423 l2info
->cookie_type
= LS_COOKIE
;
424 l2info
->cookie_len
+= 2;
425 l2info
->header_len
+= 2;
426 l2info
->bundle
= l2info
->cookie
[1];
427 } else l2info
->bundle
= l2info
->cookie
[0];
430 printf("%s-PIC, cookie-len %u, cookie 0x",
434 for (idx
= 0; idx
< l2info
->cookie_len
; idx
++) {
435 l2info
->cookie
[idx
] = p
[idx
]; /* copy cookie data */
436 if (eflag
) printf("%02x",p
[idx
]);
439 if (eflag
) printf(": "); /* print demarc b/w L2/L3*/
442 l2info
->proto
= EXTRACT_16BITS(p
+l2info
->cookie_len
);
447 p
+=l2info
->cookie_len
;
449 /* DLT_ specific parsing */
450 switch(l2info
->pictype
) {
452 if (l2info
->cookie_type
== LS_COOKIE
) {
453 l2info
->bundle
= l2info
->cookie
[1];
455 l2info
->bundle
= l2info
->cookie
[0];
458 case JUNIPER_MLFR
: /* fall through */
460 if (l2info
->cookie_type
== LS_COOKIE
) {
461 l2info
->bundle
= l2info
->cookie
[1];
463 l2info
->bundle
= l2info
->cookie
[0];
465 l2info
->proto
= EXTRACT_16BITS(p
);
466 l2info
->header_len
+= 2;
478 printf("hlen %u, proto 0x%04x, ",l2info
->header_len
,l2info
->proto
);
480 return 1; /* everything went ok so far. continue parsing */
486 * c-style: whitesmith