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