]> The Tcpdump Group git mirrors - tcpdump/blob - print-juniper.c
add support for printing Multi-Link Frame Relay
[tcpdump] / print-juniper.c
1 /*
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.
12 *
13 * Original code by Hannes Gredler (hannes@juniper.net)
14 */
15
16 #ifndef lint
17 static const char rcsid[] _U_ =
18 "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.6 2005-01-27 10:17:58 hannes Exp $ (LBL)";
19 #endif
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <tcpdump-stdinc.h>
26
27 #include <pcap.h>
28 #include <stdio.h>
29
30 #include "interface.h"
31 #include "extract.h"
32 #include "ppp.h"
33 #include "llc.h"
34 #include "nlpid.h"
35
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
41 #define LS_COOKIE_ID 0x54
42 #define LS_MLFR_LEN 4
43 #define ML_MLFR_LEN 2
44
45 #define ATM2_PKT_TYPE_MASK 0x70
46 #define ATM2_GAP_COUNT_MASK 0x3F
47
48 int ip_heuristic_guess(register const u_char *, u_int);
49 int juniper_ppp_heuristic_guess(register const u_char *, u_int);
50 static int juniper_parse_header (const u_char *, u_int8_t *, u_int);
51
52 u_int
53 juniper_mlfr_print(const struct pcap_pkthdr *h, register const u_char *p)
54 {
55 register u_int length = h->len;
56 register u_int caplen = h->caplen;
57 u_int8_t direction,bundle,cookie_len;
58 u_int32_t cookie,proto,frelay_len = 0;
59
60 if(juniper_parse_header(p, &direction,length) == 0)
61 return 0;
62
63 p+=4;
64 length-=4;
65 caplen-=4;
66
67 if (p[0] == LS_COOKIE_ID) {
68 cookie=EXTRACT_32BITS(p);
69 if (eflag) printf("LSPIC-MLFR cookie 0x%08x, ",cookie);
70 cookie_len = LS_MLFR_LEN;
71 bundle = cookie & 0xff;
72 } else {
73 cookie=EXTRACT_16BITS(p);
74 if (eflag) printf("MLPIC-MLFR cookie 0x%04x, ",cookie);
75 cookie_len = ML_MLFR_LEN;
76 bundle = (cookie >> 8) & 0xff;
77 }
78
79 proto = EXTRACT_16BITS(p+cookie_len);
80 p += cookie_len+2;
81 length-= cookie_len+2;
82 caplen-= cookie_len+2;
83
84 /* suppress Bundle-ID if frame was captured on a child-link */
85 if (eflag && cookie != 1) printf("Bundle-ID %u, ",bundle);
86
87 switch (proto) {
88 case (LLC_UI):
89 case (LLC_UI<<8):
90 isoclns_print(p, length, caplen);
91 break;
92 case (LLC_UI<<8 | NLPID_Q933):
93 case (LLC_UI<<8 | NLPID_IP):
94 case (LLC_UI<<8 | NLPID_IP6):
95 isoclns_print(p-1, length+1, caplen+1); /* pass IP{4,6} to the OSI layer for proper link-layer printing */
96 break;
97 default:
98 printf("unknown protocol 0x%04x, length %u",proto, length);
99 }
100
101 return cookie_len + frelay_len;
102 }
103
104 /*
105 * ATM1 PIC cookie format
106 *
107 * +-----+-------------------------+-------------------------------+
108 * |fmtid| vc index | channel ID |
109 * +-----+-------------------------+-------------------------------+
110 */
111
112 u_int
113 juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p)
114 {
115 register u_int length = h->len;
116 register u_int caplen = h->caplen;
117 u_int16_t extracted_ethertype;
118 u_int8_t direction;
119 u_int32_t cookie1;
120
121 if(juniper_parse_header(p, &direction,length) == 0)
122 return 0;
123
124 p+=4;
125 length-=4;
126 caplen-=4;
127
128 cookie1=EXTRACT_32BITS(p);
129
130 if (eflag) {
131 /* FIXME decode channel-id, vc-index, fmt-id
132 for once lets just hexdump the cookie */
133
134 printf("ATM1 cookie 0x%08x, ", cookie1);
135 }
136
137 p+=4;
138 length-=4;
139 caplen-=4;
140
141 if ((cookie1 >> 24) == 0x80) { /* OAM cell ? */
142 oam_print(p,length);
143 return 0;
144 }
145
146 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
147 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
148
149 if (llc_print(p, length, caplen, NULL, NULL,
150 &extracted_ethertype) != 0)
151 return 8;
152 }
153
154 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
155 isoclns_print(p + 1, length - 1, caplen - 1);
156 /* FIXME check if frame was recognized */
157 return 8;
158 }
159
160 if(ip_heuristic_guess(p, length) != 0) /* last try - vcmux encaps ? */
161 return 0;
162
163 return (8);
164 }
165
166 /*
167 * ATM2 PIC cookie format
168 *
169 * +-------------------------------+---------+---+-----+-----------+
170 * | channel ID | reserv |AAL| CCRQ| gap cnt |
171 * +-------------------------------+---------+---+-----+-----------+
172 */
173
174 u_int
175 juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p)
176 {
177 register u_int length = h->len;
178 register u_int caplen = h->caplen;
179 u_int16_t extracted_ethertype;
180 u_int8_t direction;
181 u_int32_t cookie1,cookie2;
182
183 if(juniper_parse_header(p, &direction,length) == 0)
184 return 0;
185
186 p+=4;
187 length-=4;
188 caplen-=4;
189
190 cookie1=EXTRACT_32BITS(p);
191 cookie2=EXTRACT_32BITS(p+4);
192
193 if (eflag) {
194 /* FIXME decode channel, fmt-id, ccrq, aal, gap cnt
195 for once lets just hexdump the cookie */
196
197 printf("ATM2 cookie 0x%08x%08x, ",
198 EXTRACT_32BITS(p),
199 EXTRACT_32BITS(p+4));
200 }
201
202 p+=8;
203 length-=8;
204 caplen-=8;
205
206 if (cookie2 & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
207 oam_print(p,length);
208 return 12;
209 }
210
211 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
212 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
213
214 if (llc_print(p, length, caplen, NULL, NULL,
215 &extracted_ethertype) != 0)
216 return 12;
217 }
218
219 if (direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
220 (cookie1 & ATM2_GAP_COUNT_MASK)) {
221 ether_print(p, length, caplen);
222 return 12;
223 }
224
225 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
226 isoclns_print(p + 1, length - 1, caplen - 1);
227 /* FIXME check if frame was recognized */
228 return 12;
229 }
230
231 if(juniper_ppp_heuristic_guess(p, length) != 0) /* PPPoA vcmux encaps ? */
232 return 12;
233
234 if(ip_heuristic_guess(p, length) != 0) /* last try - vcmux encaps ? */
235 return 12;
236
237 return (12);
238 }
239
240
241 /* try to guess, based on all PPP protos that are supported in
242 * a juniper router if the payload data is encapsulated using PPP */
243 int
244 juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
245
246 switch(EXTRACT_16BITS(p)) {
247 case PPP_IP :
248 case PPP_OSI :
249 case PPP_MPLS_UCAST :
250 case PPP_MPLS_MCAST :
251 case PPP_IPCP :
252 case PPP_OSICP :
253 case PPP_MPLSCP :
254 case PPP_LCP :
255 case PPP_PAP :
256 case PPP_CHAP :
257 case PPP_ML :
258 #ifdef INET6
259 case PPP_IPV6 :
260 case PPP_IPV6CP :
261 #endif
262 ppp_print(p, length);
263 break;
264
265 default:
266 return 0; /* did not find a ppp header */
267 break;
268 }
269 return 1; /* we printed a ppp packet */
270 }
271
272 int
273 ip_heuristic_guess(register const u_char *p, u_int length) {
274
275 switch(p[0]) {
276 case 0x45:
277 case 0x46:
278 case 0x47:
279 case 0x48:
280 case 0x49:
281 case 0x4a:
282 case 0x4b:
283 case 0x4c:
284 case 0x4d:
285 case 0x4e:
286 case 0x4f:
287 ip_print(p, length);
288 break;
289 #ifdef INET6
290 case 0x60:
291 case 0x61:
292 case 0x62:
293 case 0x63:
294 case 0x64:
295 case 0x65:
296 case 0x66:
297 case 0x67:
298 case 0x68:
299 case 0x69:
300 case 0x6a:
301 case 0x6b:
302 case 0x6c:
303 case 0x6d:
304 case 0x6e:
305 case 0x6f:
306 ip6_print(p, length);
307 break;
308 #endif
309 default:
310 return 0; /* did not find a ip header */
311 break;
312 }
313 return 1; /* we printed an v4/v6 packet */
314 }
315
316 static int
317 juniper_parse_header (const u_char *p, u_int8_t *direction, u_int length) {
318
319 *direction = p[3]&JUNIPER_BPF_PKT_IN;
320
321 if (EXTRACT_24BITS(p) != 0x4d4743) /* magic number found ? */
322 return -1;
323
324 if (*direction == JUNIPER_BPF_PKT_IN) {
325 if (eflag)
326 printf("%3s ", "In");
327 }
328 else {
329 if (eflag)
330 printf("%3s ", "Out");
331 }
332
333 if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
334 if (eflag)
335 printf("no-L2-hdr, ");
336
337 /* there is no link-layer present -
338 * perform the v4/v6 heuristics
339 * to figure out what it is
340 */
341 if(ip_heuristic_guess(p+8,length-8) == 0)
342 printf("no IP-hdr found!");
343
344 return 0; /* stop parsing the output further */
345
346 }
347 return 1; /* everything went ok so far. continue parsing */
348 }