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