]> The Tcpdump Group git mirrors - tcpdump/blob - print-juniper.c
#ifdef references to various Juniper DLT_ values, so that we can build
[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.25 2005-07-29 23:51:16 guy 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 "addrtoname.h"
32 #include "extract.h"
33 #include "ppp.h"
34 #include "llc.h"
35 #include "nlpid.h"
36 #include "ethertype.h"
37 #include "atm.h"
38
39 #define JUNIPER_BPF_OUT 0 /* Outgoing packet */
40 #define JUNIPER_BPF_IN 1 /* Incoming packet */
41 #define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */
42 #define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */
43 #define JUNIPER_MGC_NUMBER 0x4d4743 /* = "MGC" */
44
45 #define JUNIPER_LSQ_COOKIE_RE (1 << 3)
46 #define JUNIPER_LSQ_COOKIE_DIR (1 << 2)
47 #define JUNIPER_LSQ_L3_PROTO_SHIFT 4
48 #define JUNIPER_LSQ_L3_PROTO_MASK (0x17 << JUNIPER_LSQ_L3_PROTO_SHIFT)
49 #define JUNIPER_LSQ_L3_PROTO_IPV4 (0 << JUNIPER_LSQ_L3_PROTO_SHIFT)
50 #define JUNIPER_LSQ_L3_PROTO_IPV6 (1 << JUNIPER_LSQ_L3_PROTO_SHIFT)
51 #define JUNIPER_LSQ_L3_PROTO_MPLS (2 << JUNIPER_LSQ_L3_PROTO_SHIFT)
52 #define JUNIPER_LSQ_L3_PROTO_ISO (3 << JUNIPER_LSQ_L3_PROTO_SHIFT)
53 #define AS_PIC_COOKIE_LEN 8
54
55 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE 1
56 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE 2
57 #define JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE 3
58 #define JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE 4
59 #define JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE 5
60
61 static struct tok juniper_ipsec_type_values[] = {
62 { JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE, "ESP ENCR-AUTH" },
63 { JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE, "ESP ENCR-AH AUTH" },
64 { JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE, "ESP AUTH" },
65 { JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE, "AH AUTH" },
66 { JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE, "ESP ENCR" },
67 { 0, NULL}
68 };
69
70 static struct tok juniper_direction_values[] = {
71 { JUNIPER_BPF_IN, "In"},
72 { JUNIPER_BPF_OUT, "Out"},
73 { 0, NULL}
74 };
75
76 struct juniper_cookie_table_t {
77 u_int32_t pictype; /* pic type */
78 u_int8_t cookie_len; /* cookie len */
79 const char *s; /* pic name */
80 };
81
82 static struct juniper_cookie_table_t juniper_cookie_table[] = {
83 #ifdef DLT_JUNIPER_ATM1
84 { DLT_JUNIPER_ATM1, 4, "ATM1"},
85 #endif
86 #ifdef DLT_JUNIPER_ATM2
87 { DLT_JUNIPER_ATM2, 8, "ATM2"},
88 #endif
89 #ifdef DLT_JUNIPER_MLPPP
90 { DLT_JUNIPER_MLPPP, 2, "MLPPP"},
91 #endif
92 #ifdef DLT_JUNIPER_MLFR
93 { DLT_JUNIPER_MLFR, 2, "MLFR"},
94 #endif
95 #ifdef DLT_JUNIPER_MFR
96 { DLT_JUNIPER_MFR, 4, "MFR"},
97 #endif
98 #ifdef DLT_JUNIPER_PPPOE
99 { DLT_JUNIPER_PPPOE, 0, "PPPoE"},
100 #endif
101 #ifdef DLT_JUNIPER_PPPOE_ATM
102 { DLT_JUNIPER_PPPOE_ATM, 0, "PPPoE ATM"},
103 #endif
104 #ifdef DLT_JUNIPER_GGSN
105 { DLT_JUNIPER_GGSN, 8, "GGSN"},
106 #endif
107 #ifdef DLT_JUNIPER_MONITOR
108 { DLT_JUNIPER_MONITOR, 8, "MONITOR"},
109 #endif
110 #ifdef DLT_JUNIPER_SERVICES
111 { DLT_JUNIPER_SERVICES, 8, "AS"},
112 #endif
113 #ifdef DLT_JUNIPER_ES
114 { DLT_JUNIPER_ES, 0, "ES"},
115 #endif
116 { 0, 0, NULL }
117 };
118
119 struct juniper_l2info_t {
120 u_int32_t length;
121 u_int32_t caplen;
122 u_int32_t pictype;
123 u_int8_t direction;
124 u_int8_t header_len;
125 u_int8_t cookie_len;
126 u_int8_t cookie_type;
127 u_int8_t cookie[8];
128 u_int8_t bundle;
129 u_int16_t proto;
130 };
131
132 #define LS_COOKIE_ID 0x54
133 #define AS_COOKIE_ID 0x47
134 #define LS_MLFR_COOKIE_LEN 4
135 #define ML_MLFR_COOKIE_LEN 2
136 #define LS_MFR_COOKIE_LEN 6
137 #define ATM1_COOKIE_LEN 4
138 #define ATM2_COOKIE_LEN 8
139
140 #define ATM2_PKT_TYPE_MASK 0x70
141 #define ATM2_GAP_COUNT_MASK 0x3F
142
143 #define JUNIPER_PROTO_NULL 1
144 #define JUNIPER_PROTO_IPV4 2
145 #define JUNIPER_PROTO_IPV6 6
146
147 #define MFR_BE_MASK 0xc0
148
149 static struct tok juniper_protocol_values[] = {
150 { JUNIPER_PROTO_NULL, "Null" },
151 { JUNIPER_PROTO_IPV4, "IPv4" },
152 { JUNIPER_PROTO_IPV6, "IPv6" },
153 { 0, NULL}
154 };
155
156 int ip_heuristic_guess(register const u_char *, u_int);
157 int juniper_ppp_heuristic_guess(register const u_char *, u_int);
158 static int juniper_parse_header (const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
159
160 #ifdef DLT_JUNIPER_GGSN
161 u_int
162 juniper_ggsn_print(const struct pcap_pkthdr *h, register const u_char *p)
163 {
164 struct juniper_l2info_t l2info;
165 struct juniper_ggsn_header {
166 u_int8_t svc_id;
167 u_int8_t flags_len;
168 u_int8_t proto;
169 u_int8_t flags;
170 u_int8_t vlan_id[2];
171 u_int8_t res[2];
172 };
173 const struct juniper_ggsn_header *gh;
174
175 l2info.pictype = DLT_JUNIPER_GGSN;
176 if(juniper_parse_header(p, h, &l2info) == 0)
177 return l2info.header_len;
178
179 p+=l2info.header_len;
180 gh = (struct juniper_ggsn_header *)p;
181
182 if (eflag)
183 printf("proto %s (%u), vlan %u: ",
184 tok2str(juniper_protocol_values,"Unknown",gh->proto),
185 gh->proto,
186 EXTRACT_16BITS(&gh->vlan_id[0]));
187
188 switch (gh->proto) {
189 case JUNIPER_PROTO_IPV4:
190 ip_print(gndo, p, l2info.length);
191 break;
192 #ifdef INET6
193 case JUNIPER_PROTO_IPV6:
194 ip6_print(p, l2info.length);
195 break;
196 #endif /* INET6 */
197 default:
198 if (!eflag)
199 printf("unknown GGSN proto (%u)", gh->proto);
200 }
201
202 return l2info.header_len;
203 }
204 #endif
205
206 #ifdef DLT_JUNIPER_ES
207 u_int
208 juniper_es_print(const struct pcap_pkthdr *h, register const u_char *p)
209 {
210 struct juniper_l2info_t l2info;
211 struct juniper_ipsec_header {
212 u_int8_t sa_index[2];
213 u_int8_t ttl;
214 u_int8_t type;
215 u_int8_t spi[4];
216 u_int8_t src_ip[4];
217 u_int8_t dst_ip[4];
218 };
219 u_int rewrite_len,es_type_bundle;
220 const struct juniper_ipsec_header *ih;
221
222 l2info.pictype = DLT_JUNIPER_ES;
223 if(juniper_parse_header(p, h, &l2info) == 0)
224 return l2info.header_len;
225
226 p+=l2info.header_len;
227 ih = (struct juniper_ipsec_header *)p;
228
229 switch (ih->type) {
230 case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE:
231 case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE:
232 rewrite_len = 0;
233 es_type_bundle = 1;
234 break;
235 case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE:
236 case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE:
237 case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE:
238 rewrite_len = 16;
239 es_type_bundle = 0;
240 default:
241 printf("ES Invalid type %u, length %u",
242 ih->type,
243 l2info.length);
244 return l2info.header_len;
245 }
246
247 l2info.length-=rewrite_len;
248 p+=rewrite_len;
249
250 if (eflag) {
251 if (!es_type_bundle) {
252 printf("ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n",
253 EXTRACT_16BITS(&ih->sa_index),
254 ih->ttl,
255 tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
256 ih->type,
257 EXTRACT_32BITS(&ih->spi),
258 ipaddr_string(EXTRACT_32BITS(&ih->src_ip)),
259 ipaddr_string(EXTRACT_32BITS(&ih->dst_ip)),
260 l2info.length);
261 } else {
262 printf("ES SA, index %u, ttl %u type %s (%u), length %u\n",
263 EXTRACT_16BITS(&ih->sa_index),
264 ih->ttl,
265 tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
266 ih->type,
267 l2info.length);
268 }
269 }
270
271 ip_print(gndo, p, l2info.length);
272 return l2info.header_len;
273 }
274 #endif
275
276 #ifdef DLT_JUNIPER_MONITOR
277 u_int
278 juniper_monitor_print(const struct pcap_pkthdr *h, register const u_char *p)
279 {
280 struct juniper_l2info_t l2info;
281 struct juniper_monitor_header {
282 u_int8_t pkt_type;
283 u_int8_t padding;
284 u_int8_t iif[2];
285 u_int8_t service_id[4];
286 };
287 const struct juniper_monitor_header *mh;
288
289 l2info.pictype = DLT_JUNIPER_MONITOR;
290 if(juniper_parse_header(p, h, &l2info) == 0)
291 return l2info.header_len;
292
293 p+=l2info.header_len;
294 mh = (struct juniper_monitor_header *)p;
295
296 if (eflag)
297 printf("service-id %u, iif %u, pkt-type %u: ",
298 EXTRACT_32BITS(&mh->service_id),
299 EXTRACT_16BITS(&mh->iif),
300 mh->pkt_type);
301
302 /* no proto field - lets guess by first byte of IP header*/
303 ip_heuristic_guess(p, l2info.length);
304
305 return l2info.header_len;
306 }
307 #endif
308
309 #ifdef DLT_JUNIPER_SERVICES
310 u_int
311 juniper_services_print(const struct pcap_pkthdr *h, register const u_char *p)
312 {
313 struct juniper_l2info_t l2info;
314 struct juniper_services_header {
315 u_int8_t svc_id;
316 u_int8_t flags_len;
317 u_int8_t svc_set_id[2];
318 u_int8_t dir_iif[4];
319 };
320 const struct juniper_services_header *sh;
321
322 l2info.pictype = DLT_JUNIPER_SERVICES;
323 if(juniper_parse_header(p, h, &l2info) == 0)
324 return l2info.header_len;
325
326 p+=l2info.header_len;
327 sh = (struct juniper_services_header *)p;
328
329 if (eflag)
330 printf("service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ",
331 sh->svc_id,
332 sh->flags_len,
333 EXTRACT_16BITS(&sh->svc_set_id),
334 EXTRACT_24BITS(&sh->dir_iif[1]));
335
336 /* no proto field - lets guess by first byte of IP header*/
337 ip_heuristic_guess(p, l2info.length);
338
339 return l2info.header_len;
340 }
341 #endif
342
343 #ifdef DLT_JUNIPER_PPPOE
344 u_int
345 juniper_pppoe_print(const struct pcap_pkthdr *h, register const u_char *p)
346 {
347 struct juniper_l2info_t l2info;
348
349 l2info.pictype = DLT_JUNIPER_PPPOE;
350 if(juniper_parse_header(p, h, &l2info) == 0)
351 return l2info.header_len;
352
353 p+=l2info.header_len;
354 /* this DLT contains nothing but raw ethernet frames */
355 ether_print(p, l2info.length, l2info.caplen);
356 return l2info.header_len;
357 }
358 #endif
359
360 #ifdef DLT_JUNIPER_PPPOE_ATM
361 u_int
362 juniper_pppoe_atm_print(const struct pcap_pkthdr *h, register const u_char *p)
363 {
364 struct juniper_l2info_t l2info;
365 u_int16_t extracted_ethertype;
366
367 l2info.pictype = DLT_JUNIPER_PPPOE_ATM;
368 if(juniper_parse_header(p, h, &l2info) == 0)
369 return l2info.header_len;
370
371 p+=l2info.header_len;
372
373 extracted_ethertype = EXTRACT_16BITS(p);
374 /* this DLT contains nothing but raw PPPoE frames,
375 * prepended with a type field*/
376 if (ether_encap_print(extracted_ethertype,
377 p+ETHERTYPE_LEN,
378 l2info.length-ETHERTYPE_LEN,
379 l2info.caplen-ETHERTYPE_LEN,
380 &extracted_ethertype) == 0)
381 /* ether_type not known, probably it wasn't one */
382 printf("unknown ethertype 0x%04x", extracted_ethertype);
383
384 return l2info.header_len;
385 }
386 #endif
387
388 #ifdef DLT_JUNIPER_MLPPP
389 u_int
390 juniper_mlppp_print(const struct pcap_pkthdr *h, register const u_char *p)
391 {
392 struct juniper_l2info_t l2info;
393
394 l2info.pictype = DLT_JUNIPER_MLPPP;
395 if(juniper_parse_header(p, h, &l2info) == 0)
396 return l2info.header_len;
397
398 /* suppress Bundle-ID if frame was captured on a child-link
399 * best indicator if the cookie looks like a proto */
400 if (eflag &&
401 EXTRACT_16BITS(&l2info.cookie) != PPP_OSI &&
402 EXTRACT_16BITS(&l2info.cookie) != (PPP_ADDRESS << 8 | PPP_CONTROL))
403 printf("Bundle-ID %u: ",l2info.bundle);
404
405 p+=l2info.header_len;
406
407 /* first try the LSQ protos */
408 switch(l2info.proto) {
409 case JUNIPER_LSQ_L3_PROTO_IPV4:
410 /* IP traffic going to the RE would not have a cookie
411 * -> this must be incoming IS-IS over PPP
412 */
413 if (l2info.cookie[4] == (JUNIPER_LSQ_COOKIE_RE|JUNIPER_LSQ_COOKIE_DIR))
414 ppp_print(p, l2info.length);
415 else
416 ip_print(gndo, p, l2info.length);
417 return l2info.header_len;
418 #ifdef INET6
419 case JUNIPER_LSQ_L3_PROTO_IPV6:
420 ip6_print(p,l2info.length);
421 return l2info.header_len;
422 #endif
423 case JUNIPER_LSQ_L3_PROTO_MPLS:
424 mpls_print(p,l2info.length);
425 return l2info.header_len;
426 case JUNIPER_LSQ_L3_PROTO_ISO:
427 isoclns_print(p,l2info.length,l2info.caplen);
428 return l2info.header_len;
429 default:
430 break;
431 }
432
433 /* zero length cookie ? */
434 switch (EXTRACT_16BITS(&l2info.cookie)) {
435 case PPP_OSI:
436 ppp_print(p-2,l2info.length+2);
437 break;
438 case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */
439 default:
440 ppp_print(p,l2info.length);
441 break;
442 }
443
444 return l2info.header_len;
445 }
446 #endif
447
448
449 #ifdef DLT_JUNIPER_MFR
450 u_int
451 juniper_mfr_print(const struct pcap_pkthdr *h, register const u_char *p)
452 {
453 struct juniper_l2info_t l2info;
454
455 l2info.pictype = DLT_JUNIPER_MFR;
456 if(juniper_parse_header(p, h, &l2info) == 0)
457 return l2info.header_len;
458
459 p+=l2info.header_len;
460
461 /* child-link ? */
462 if (l2info.cookie_len == 0) {
463 mfr_print(p,l2info.length);
464 return l2info.header_len;
465 }
466
467 /* first try the LSQ protos */
468 if (l2info.cookie_len == AS_PIC_COOKIE_LEN) {
469 switch(l2info.proto) {
470 case JUNIPER_LSQ_L3_PROTO_IPV4:
471 ip_print(gndo, p, l2info.length);
472 return l2info.header_len;
473 #ifdef INET6
474 case JUNIPER_LSQ_L3_PROTO_IPV6:
475 ip6_print(p,l2info.length);
476 return l2info.header_len;
477 #endif
478 case JUNIPER_LSQ_L3_PROTO_MPLS:
479 mpls_print(p,l2info.length);
480 return l2info.header_len;
481 case JUNIPER_LSQ_L3_PROTO_ISO:
482 isoclns_print(p,l2info.length,l2info.caplen);
483 return l2info.header_len;
484 default:
485 break;
486 }
487 return l2info.header_len;
488 }
489
490 /* suppress Bundle-ID if frame was captured on a child-link */
491 if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
492 switch (l2info.proto) {
493 case (LLCSAP_ISONS<<8 | LLCSAP_ISONS):
494 isoclns_print(p+1, l2info.length-1, l2info.caplen-1);
495 break;
496 case (LLC_UI<<8 | NLPID_Q933):
497 case (LLC_UI<<8 | NLPID_IP):
498 case (LLC_UI<<8 | NLPID_IP6):
499 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
500 isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
501 break;
502 default:
503 printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
504 }
505
506 return l2info.header_len;
507 }
508 #endif
509
510 #ifdef DLT_JUNIPER_MLFR
511 u_int
512 juniper_mlfr_print(const struct pcap_pkthdr *h, register const u_char *p)
513 {
514 struct juniper_l2info_t l2info;
515
516 l2info.pictype = DLT_JUNIPER_MLFR;
517 if(juniper_parse_header(p, h, &l2info) == 0)
518 return l2info.header_len;
519
520 p+=l2info.header_len;
521
522 /* suppress Bundle-ID if frame was captured on a child-link */
523 if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
524 switch (l2info.proto) {
525 case (LLC_UI):
526 case (LLC_UI<<8):
527 isoclns_print(p, l2info.length, l2info.caplen);
528 break;
529 case (LLC_UI<<8 | NLPID_Q933):
530 case (LLC_UI<<8 | NLPID_IP):
531 case (LLC_UI<<8 | NLPID_IP6):
532 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
533 isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
534 break;
535 default:
536 printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
537 }
538
539 return l2info.header_len;
540 }
541 #endif
542
543 /*
544 * ATM1 PIC cookie format
545 *
546 * +-----+-------------------------+-------------------------------+
547 * |fmtid| vc index | channel ID |
548 * +-----+-------------------------+-------------------------------+
549 */
550
551 #ifdef DLT_JUNIPER_ATM1
552 u_int
553 juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p)
554 {
555 u_int16_t extracted_ethertype;
556
557 struct juniper_l2info_t l2info;
558
559 l2info.pictype = DLT_JUNIPER_ATM1;
560 if(juniper_parse_header(p, h, &l2info) == 0)
561 return l2info.header_len;
562
563 p+=l2info.header_len;
564
565 if (l2info.cookie[0] == 0x80) { /* OAM cell ? */
566 oam_print(p,l2info.length,ATM_OAM_NOHEC);
567 return l2info.header_len;
568 }
569
570 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
571 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
572
573 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
574 &extracted_ethertype) != 0)
575 return l2info.header_len;
576 }
577
578 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
579 isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
580 /* FIXME check if frame was recognized */
581 return l2info.header_len;
582 }
583
584 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
585 return l2info.header_len;
586
587 return l2info.header_len;
588 }
589 #endif
590
591 /*
592 * ATM2 PIC cookie format
593 *
594 * +-------------------------------+---------+---+-----+-----------+
595 * | channel ID | reserv |AAL| CCRQ| gap cnt |
596 * +-------------------------------+---------+---+-----+-----------+
597 */
598
599 #ifdef DLT_JUNIPER_ATM2
600 u_int
601 juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p)
602 {
603 u_int16_t extracted_ethertype;
604 u_int32_t control_word;
605
606 struct juniper_l2info_t l2info;
607
608 l2info.pictype = DLT_JUNIPER_ATM2;
609 if(juniper_parse_header(p, h, &l2info) == 0)
610 return l2info.header_len;
611
612 p+=l2info.header_len;
613
614 if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
615 control_word = EXTRACT_32BITS(p);
616 if(control_word == 0 || control_word == 0x08000000) {
617 l2info.header_len += 4;
618 l2info.length -= 4;
619 p += 4;
620 }
621 oam_print(p,l2info.length,ATM_OAM_NOHEC);
622 return l2info.header_len;
623 }
624
625 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
626 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
627
628 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
629 &extracted_ethertype) != 0)
630 return l2info.header_len;
631 }
632
633 if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
634 (EXTRACT_32BITS(l2info.cookie) & ATM2_GAP_COUNT_MASK)) {
635 ether_print(p, l2info.length, l2info.caplen);
636 return l2info.header_len;
637 }
638
639 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
640 isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
641 /* FIXME check if frame was recognized */
642 return l2info.header_len;
643 }
644
645 if(juniper_ppp_heuristic_guess(p, l2info.length) != 0) /* PPPoA vcmux encaps ? */
646 return l2info.header_len;
647
648 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
649 return l2info.header_len;
650
651 return l2info.header_len;
652 }
653 #endif
654
655
656 /* try to guess, based on all PPP protos that are supported in
657 * a juniper router if the payload data is encapsulated using PPP */
658 int
659 juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
660
661 switch(EXTRACT_16BITS(p)) {
662 case PPP_IP :
663 case PPP_OSI :
664 case PPP_MPLS_UCAST :
665 case PPP_MPLS_MCAST :
666 case PPP_IPCP :
667 case PPP_OSICP :
668 case PPP_MPLSCP :
669 case PPP_LCP :
670 case PPP_PAP :
671 case PPP_CHAP :
672 case PPP_ML :
673 #ifdef INET6
674 case PPP_IPV6 :
675 case PPP_IPV6CP :
676 #endif
677 ppp_print(p, length);
678 break;
679
680 default:
681 return 0; /* did not find a ppp header */
682 break;
683 }
684 return 1; /* we printed a ppp packet */
685 }
686
687 int
688 ip_heuristic_guess(register const u_char *p, u_int length) {
689
690 switch(p[0]) {
691 case 0x45:
692 case 0x46:
693 case 0x47:
694 case 0x48:
695 case 0x49:
696 case 0x4a:
697 case 0x4b:
698 case 0x4c:
699 case 0x4d:
700 case 0x4e:
701 case 0x4f:
702 ip_print(gndo, p, length);
703 break;
704 #ifdef INET6
705 case 0x60:
706 case 0x61:
707 case 0x62:
708 case 0x63:
709 case 0x64:
710 case 0x65:
711 case 0x66:
712 case 0x67:
713 case 0x68:
714 case 0x69:
715 case 0x6a:
716 case 0x6b:
717 case 0x6c:
718 case 0x6d:
719 case 0x6e:
720 case 0x6f:
721 ip6_print(p, length);
722 break;
723 #endif
724 default:
725 return 0; /* did not find a ip header */
726 break;
727 }
728 return 1; /* we printed an v4/v6 packet */
729 }
730
731 static int
732 juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) {
733
734 struct juniper_cookie_table_t *lp = juniper_cookie_table;
735 u_int idx;
736
737 l2info->header_len = 0;
738 l2info->cookie_len = 0;
739 l2info->proto = 0;
740
741
742 l2info->length = h->len;
743 l2info->caplen = h->caplen;
744 l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
745
746 TCHECK2(p[0],4);
747 if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */
748 printf("no magic-number found!");
749 return 0;
750 } else
751 l2info->header_len = 4;
752
753 if (eflag) /* print direction */
754 printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction));
755
756 if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
757 if (eflag)
758 printf("no-L2-hdr, ");
759
760 /* there is no link-layer present -
761 * perform the v4/v6 heuristics
762 * to figure out what it is
763 */
764 TCHECK2(p[8],1);
765 if(ip_heuristic_guess(p+8,l2info->length-8) == 0)
766 printf("no IP-hdr found!");
767
768 l2info->header_len+=4;
769 return 0; /* stop parsing the output further */
770
771 }
772
773 p+=l2info->header_len;
774 l2info->length -= l2info->header_len;
775 l2info->caplen -= l2info->header_len;
776
777 /* search through the cookie table and copy values matching for our PIC type */
778 while (lp->s != NULL) {
779 if (lp->pictype == l2info->pictype) {
780
781 l2info->cookie_len += lp->cookie_len;
782
783 switch (p[0]) {
784 case LS_COOKIE_ID:
785 l2info->cookie_type = LS_COOKIE_ID;
786 l2info->cookie_len += 2;
787 break;
788 case AS_COOKIE_ID:
789 l2info->cookie_type = AS_COOKIE_ID;
790 l2info->cookie_len = 8;
791 break;
792
793 default:
794 l2info->bundle = l2info->cookie[0];
795 break;
796 }
797
798
799 #ifdef DLT_JUNIPER_MFR
800 /* MFR child links don't carry cookies */
801 if (l2info->pictype == DLT_JUNIPER_MFR &&
802 (p[0] & MFR_BE_MASK) == MFR_BE_MASK) {
803 l2info->cookie_len = 0;
804 }
805 #endif
806
807 l2info->header_len += l2info->cookie_len;
808 l2info->length -= l2info->cookie_len;
809 l2info->caplen -= l2info->cookie_len;
810
811 if (eflag)
812 printf("%s-PIC, cookie-len %u",
813 lp->s,
814 l2info->cookie_len);
815
816 if (l2info->cookie_len > 0) {
817 TCHECK2(p[0],l2info->cookie_len);
818 if (eflag)
819 printf(", cookie 0x");
820 for (idx = 0; idx < l2info->cookie_len; idx++) {
821 l2info->cookie[idx] = p[idx]; /* copy cookie data */
822 if (eflag) printf("%02x",p[idx]);
823 }
824 }
825
826 if (eflag) printf(": "); /* print demarc b/w L2/L3*/
827
828
829 l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len);
830 break;
831 }
832 ++lp;
833 }
834 p+=l2info->cookie_len;
835
836 /* DLT_ specific parsing */
837 switch(l2info->pictype) {
838 #ifdef DLT_JUNIPER_MLPPP
839 case DLT_JUNIPER_MLPPP:
840 switch (l2info->cookie_type) {
841 case LS_COOKIE_ID:
842 l2info->bundle = l2info->cookie[1];
843 break;
844 case AS_COOKIE_ID:
845 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
846 l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
847 break;
848 default:
849 l2info->bundle = l2info->cookie[0];
850 break;
851 }
852 break;
853 #endif
854 #ifdef DLT_JUNIPER_MLFR
855 case DLT_JUNIPER_MLFR:
856 switch (l2info->cookie_type) {
857 case LS_COOKIE_ID:
858 l2info->bundle = l2info->cookie[1];
859 l2info->proto = EXTRACT_16BITS(p);
860 l2info->header_len += 2;
861 l2info->length -= 2;
862 l2info->caplen -= 2;
863 break;
864 case AS_COOKIE_ID:
865 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
866 l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
867 break;
868 default:
869 l2info->bundle = l2info->cookie[0];
870 l2info->header_len += 2;
871 l2info->length -= 2;
872 l2info->caplen -= 2;
873 break;
874 }
875 break;
876 #endif
877 #ifdef DLT_JUNIPER_MFR
878 case DLT_JUNIPER_MFR:
879 switch (l2info->cookie_type) {
880 case LS_COOKIE_ID:
881 l2info->bundle = l2info->cookie[1];
882 l2info->proto = EXTRACT_16BITS(p);
883 l2info->header_len += 2;
884 l2info->length -= 2;
885 l2info->caplen -= 2;
886 break;
887 case AS_COOKIE_ID:
888 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
889 l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
890 break;
891 default:
892 l2info->bundle = l2info->cookie[0];
893 break;
894 }
895 break;
896 #endif
897 #ifdef DLT_JUNIPER_ATM2
898 case DLT_JUNIPER_ATM2:
899 TCHECK2(p[0],4);
900 /* ATM cell relay control word present ? */
901 if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK && *p & 0x08) {
902 l2info->header_len += 4;
903 if (eflag)
904 printf("control-word 0x%08x ",EXTRACT_32BITS(p));
905 }
906 break;
907 #endif
908 #ifdef DLT_JUNIPER_ATM1
909 case DLT_JUNIPER_ATM1:
910 break;
911 #endif
912 default:
913 printf("Unknown Juniper DLT_ type %u: ", l2info->pictype);
914 break;
915 }
916
917 if (eflag > 1)
918 printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto);
919
920 return 1; /* everything went ok so far. continue parsing */
921 trunc:
922 printf("[|juniper_hdr], length %u",h->len);
923 return 0;
924 }
925
926
927 /*
928 * Local Variables:
929 * c-style: whitesmith
930 * c-basic-offset: 4
931 * End:
932 */