Import tcpdump-3.9.7
[dragonfly/port-amd64.git] / contrib / tcpdump-3.9 / print-juniper.c
blobb5837e378573a2e0f9282e95d186a9b78a3750ba
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.
13 * Original code by Hannes Gredler (hannes@juniper.net)
16 #ifndef lint
17 static const char rcsid[] _U_ =
18 "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.8.2.22 2006/05/10 22:42:46 guy Exp $ (LBL)";
19 #endif
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
25 #include <tcpdump-stdinc.h>
27 #include <pcap.h>
28 #include <stdio.h>
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"
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" */
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
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
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}
71 static struct tok juniper_direction_values[] = {
72 { JUNIPER_BPF_IN, "In"},
73 { JUNIPER_BPF_OUT, "Out"},
74 { 0, NULL}
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 */
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 }
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;
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
141 #define ATM2_PKT_TYPE_MASK 0x70
142 #define ATM2_GAP_COUNT_MASK 0x3F
144 #define JUNIPER_PROTO_NULL 1
145 #define JUNIPER_PROTO_IPV4 2
146 #define JUNIPER_PROTO_IPV6 6
148 #define MFR_BE_MASK 0xc0
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}
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 *);
161 #ifdef DLT_JUNIPER_GGSN
162 u_int
163 juniper_ggsn_print(const struct pcap_pkthdr *h, register const u_char *p)
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];
174 const struct juniper_ggsn_header *gh;
176 l2info.pictype = DLT_JUNIPER_GGSN;
177 if(juniper_parse_header(p, h, &l2info) == 0)
178 return l2info.header_len;
180 p+=l2info.header_len;
181 gh = (struct juniper_ggsn_header *)p;
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]));
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);
203 return l2info.header_len;
205 #endif
207 #ifdef DLT_JUNIPER_ES
208 u_int
209 juniper_es_print(const struct pcap_pkthdr *h, register const u_char *p)
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];
220 u_int rewrite_len,es_type_bundle;
221 const struct juniper_ipsec_header *ih;
223 l2info.pictype = DLT_JUNIPER_ES;
224 if(juniper_parse_header(p, h, &l2info) == 0)
225 return l2info.header_len;
227 p+=l2info.header_len;
228 ih = (struct juniper_ipsec_header *)p;
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;
248 l2info.length-=rewrite_len;
249 p+=rewrite_len;
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);
272 ip_print(gndo, p, l2info.length);
273 return l2info.header_len;
275 #endif
277 #ifdef DLT_JUNIPER_MONITOR
278 u_int
279 juniper_monitor_print(const struct pcap_pkthdr *h, register const u_char *p)
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];
288 const struct juniper_monitor_header *mh;
290 l2info.pictype = DLT_JUNIPER_MONITOR;
291 if(juniper_parse_header(p, h, &l2info) == 0)
292 return l2info.header_len;
294 p+=l2info.header_len;
295 mh = (struct juniper_monitor_header *)p;
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);
303 /* no proto field - lets guess by first byte of IP header*/
304 ip_heuristic_guess(p, l2info.length);
306 return l2info.header_len;
308 #endif
310 #ifdef DLT_JUNIPER_SERVICES
311 u_int
312 juniper_services_print(const struct pcap_pkthdr *h, register const u_char *p)
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];
321 const struct juniper_services_header *sh;
323 l2info.pictype = DLT_JUNIPER_SERVICES;
324 if(juniper_parse_header(p, h, &l2info) == 0)
325 return l2info.header_len;
327 p+=l2info.header_len;
328 sh = (struct juniper_services_header *)p;
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]));
337 /* no proto field - lets guess by first byte of IP header*/
338 ip_heuristic_guess(p, l2info.length);
340 return l2info.header_len;
342 #endif
344 #ifdef DLT_JUNIPER_PPPOE
345 u_int
346 juniper_pppoe_print(const struct pcap_pkthdr *h, register const u_char *p)
348 struct juniper_l2info_t l2info;
350 l2info.pictype = DLT_JUNIPER_PPPOE;
351 if(juniper_parse_header(p, h, &l2info) == 0)
352 return l2info.header_len;
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;
359 #endif
361 #ifdef DLT_JUNIPER_ETHER
362 u_int
363 juniper_ether_print(const struct pcap_pkthdr *h, register const u_char *p)
365 struct juniper_l2info_t l2info;
367 l2info.pictype = DLT_JUNIPER_ETHER;
368 if(juniper_parse_header(p, h, &l2info) == 0)
369 return l2info.header_len;
371 p+=l2info.header_len;
372 /* this DLT contains nothing but raw Ethernet frames */
373 ether_print(p, l2info.length, l2info.caplen);
374 return l2info.header_len;
376 #endif
378 #ifdef DLT_JUNIPER_PPP
379 u_int
380 juniper_ppp_print(const struct pcap_pkthdr *h, register const u_char *p)
382 struct juniper_l2info_t l2info;
384 l2info.pictype = DLT_JUNIPER_PPP;
385 if(juniper_parse_header(p, h, &l2info) == 0)
386 return l2info.header_len;
388 p+=l2info.header_len;
389 /* this DLT contains nothing but raw ppp frames */
390 ppp_print(p, l2info.length);
391 return l2info.header_len;
393 #endif
395 #ifdef DLT_JUNIPER_FRELAY
396 u_int
397 juniper_frelay_print(const struct pcap_pkthdr *h, register const u_char *p)
399 struct juniper_l2info_t l2info;
401 l2info.pictype = DLT_JUNIPER_FRELAY;
402 if(juniper_parse_header(p, h, &l2info) == 0)
403 return l2info.header_len;
405 p+=l2info.header_len;
406 /* this DLT contains nothing but raw frame-relay frames */
407 fr_print(p, l2info.length);
408 return l2info.header_len;
410 #endif
412 #ifdef DLT_JUNIPER_CHDLC
413 u_int
414 juniper_chdlc_print(const struct pcap_pkthdr *h, register const u_char *p)
416 struct juniper_l2info_t l2info;
418 l2info.pictype = DLT_JUNIPER_CHDLC;
419 if(juniper_parse_header(p, h, &l2info) == 0)
420 return l2info.header_len;
422 p+=l2info.header_len;
423 /* this DLT contains nothing but raw c-hdlc frames */
424 chdlc_print(p, l2info.length);
425 return l2info.header_len;
427 #endif
429 #ifdef DLT_JUNIPER_PPPOE_ATM
430 u_int
431 juniper_pppoe_atm_print(const struct pcap_pkthdr *h, register const u_char *p)
433 struct juniper_l2info_t l2info;
434 u_int16_t extracted_ethertype;
436 l2info.pictype = DLT_JUNIPER_PPPOE_ATM;
437 if(juniper_parse_header(p, h, &l2info) == 0)
438 return l2info.header_len;
440 p+=l2info.header_len;
442 extracted_ethertype = EXTRACT_16BITS(p);
443 /* this DLT contains nothing but raw PPPoE frames,
444 * prepended with a type field*/
445 if (ether_encap_print(extracted_ethertype,
446 p+ETHERTYPE_LEN,
447 l2info.length-ETHERTYPE_LEN,
448 l2info.caplen-ETHERTYPE_LEN,
449 &extracted_ethertype) == 0)
450 /* ether_type not known, probably it wasn't one */
451 printf("unknown ethertype 0x%04x", extracted_ethertype);
453 return l2info.header_len;
455 #endif
457 #ifdef DLT_JUNIPER_MLPPP
458 u_int
459 juniper_mlppp_print(const struct pcap_pkthdr *h, register const u_char *p)
461 struct juniper_l2info_t l2info;
463 l2info.pictype = DLT_JUNIPER_MLPPP;
464 if(juniper_parse_header(p, h, &l2info) == 0)
465 return l2info.header_len;
467 /* suppress Bundle-ID if frame was captured on a child-link
468 * best indicator if the cookie looks like a proto */
469 if (eflag &&
470 EXTRACT_16BITS(&l2info.cookie) != PPP_OSI &&
471 EXTRACT_16BITS(&l2info.cookie) != (PPP_ADDRESS << 8 | PPP_CONTROL))
472 printf("Bundle-ID %u: ",l2info.bundle);
474 p+=l2info.header_len;
476 /* first try the LSQ protos */
477 switch(l2info.proto) {
478 case JUNIPER_LSQ_L3_PROTO_IPV4:
479 /* IP traffic going to the RE would not have a cookie
480 * -> this must be incoming IS-IS over PPP
482 if (l2info.cookie[4] == (JUNIPER_LSQ_COOKIE_RE|JUNIPER_LSQ_COOKIE_DIR))
483 ppp_print(p, l2info.length);
484 else
485 ip_print(gndo, p, l2info.length);
486 return l2info.header_len;
487 #ifdef INET6
488 case JUNIPER_LSQ_L3_PROTO_IPV6:
489 ip6_print(p,l2info.length);
490 return l2info.header_len;
491 #endif
492 case JUNIPER_LSQ_L3_PROTO_MPLS:
493 mpls_print(p,l2info.length);
494 return l2info.header_len;
495 case JUNIPER_LSQ_L3_PROTO_ISO:
496 isoclns_print(p,l2info.length,l2info.caplen);
497 return l2info.header_len;
498 default:
499 break;
502 /* zero length cookie ? */
503 switch (EXTRACT_16BITS(&l2info.cookie)) {
504 case PPP_OSI:
505 ppp_print(p-2,l2info.length+2);
506 break;
507 case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */
508 default:
509 ppp_print(p,l2info.length);
510 break;
513 return l2info.header_len;
515 #endif
518 #ifdef DLT_JUNIPER_MFR
519 u_int
520 juniper_mfr_print(const struct pcap_pkthdr *h, register const u_char *p)
522 struct juniper_l2info_t l2info;
524 l2info.pictype = DLT_JUNIPER_MFR;
525 if(juniper_parse_header(p, h, &l2info) == 0)
526 return l2info.header_len;
528 p+=l2info.header_len;
530 /* child-link ? */
531 if (l2info.cookie_len == 0) {
532 mfr_print(p,l2info.length);
533 return l2info.header_len;
536 /* first try the LSQ protos */
537 if (l2info.cookie_len == AS_PIC_COOKIE_LEN) {
538 switch(l2info.proto) {
539 case JUNIPER_LSQ_L3_PROTO_IPV4:
540 ip_print(gndo, p, l2info.length);
541 return l2info.header_len;
542 #ifdef INET6
543 case JUNIPER_LSQ_L3_PROTO_IPV6:
544 ip6_print(p,l2info.length);
545 return l2info.header_len;
546 #endif
547 case JUNIPER_LSQ_L3_PROTO_MPLS:
548 mpls_print(p,l2info.length);
549 return l2info.header_len;
550 case JUNIPER_LSQ_L3_PROTO_ISO:
551 isoclns_print(p,l2info.length,l2info.caplen);
552 return l2info.header_len;
553 default:
554 break;
556 return l2info.header_len;
559 /* suppress Bundle-ID if frame was captured on a child-link */
560 if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
561 switch (l2info.proto) {
562 case (LLCSAP_ISONS<<8 | LLCSAP_ISONS):
563 isoclns_print(p+1, l2info.length-1, l2info.caplen-1);
564 break;
565 case (LLC_UI<<8 | NLPID_Q933):
566 case (LLC_UI<<8 | NLPID_IP):
567 case (LLC_UI<<8 | NLPID_IP6):
568 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
569 isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
570 break;
571 default:
572 printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
575 return l2info.header_len;
577 #endif
579 #ifdef DLT_JUNIPER_MLFR
580 u_int
581 juniper_mlfr_print(const struct pcap_pkthdr *h, register const u_char *p)
583 struct juniper_l2info_t l2info;
585 l2info.pictype = DLT_JUNIPER_MLFR;
586 if(juniper_parse_header(p, h, &l2info) == 0)
587 return l2info.header_len;
589 p+=l2info.header_len;
591 /* suppress Bundle-ID if frame was captured on a child-link */
592 if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
593 switch (l2info.proto) {
594 case (LLC_UI):
595 case (LLC_UI<<8):
596 isoclns_print(p, l2info.length, l2info.caplen);
597 break;
598 case (LLC_UI<<8 | NLPID_Q933):
599 case (LLC_UI<<8 | NLPID_IP):
600 case (LLC_UI<<8 | NLPID_IP6):
601 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
602 isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
603 break;
604 default:
605 printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
608 return l2info.header_len;
610 #endif
613 * ATM1 PIC cookie format
615 * +-----+-------------------------+-------------------------------+
616 * |fmtid| vc index | channel ID |
617 * +-----+-------------------------+-------------------------------+
620 #ifdef DLT_JUNIPER_ATM1
621 u_int
622 juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p)
624 u_int16_t extracted_ethertype;
626 struct juniper_l2info_t l2info;
628 l2info.pictype = DLT_JUNIPER_ATM1;
629 if(juniper_parse_header(p, h, &l2info) == 0)
630 return l2info.header_len;
632 p+=l2info.header_len;
634 if (l2info.cookie[0] == 0x80) { /* OAM cell ? */
635 oam_print(p,l2info.length,ATM_OAM_NOHEC);
636 return l2info.header_len;
639 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
640 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
642 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
643 &extracted_ethertype) != 0)
644 return l2info.header_len;
647 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
648 isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
649 /* FIXME check if frame was recognized */
650 return l2info.header_len;
653 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
654 return l2info.header_len;
656 return l2info.header_len;
658 #endif
661 * ATM2 PIC cookie format
663 * +-------------------------------+---------+---+-----+-----------+
664 * | channel ID | reserv |AAL| CCRQ| gap cnt |
665 * +-------------------------------+---------+---+-----+-----------+
668 #ifdef DLT_JUNIPER_ATM2
669 u_int
670 juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p)
672 u_int16_t extracted_ethertype;
674 struct juniper_l2info_t l2info;
676 l2info.pictype = DLT_JUNIPER_ATM2;
677 if(juniper_parse_header(p, h, &l2info) == 0)
678 return l2info.header_len;
680 p+=l2info.header_len;
682 if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
683 oam_print(p,l2info.length,ATM_OAM_NOHEC);
684 return l2info.header_len;
687 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
688 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
690 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
691 &extracted_ethertype) != 0)
692 return l2info.header_len;
695 if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
696 (EXTRACT_32BITS(l2info.cookie) & ATM2_GAP_COUNT_MASK)) {
697 ether_print(p, l2info.length, l2info.caplen);
698 return l2info.header_len;
701 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
702 isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
703 /* FIXME check if frame was recognized */
704 return l2info.header_len;
707 if(juniper_ppp_heuristic_guess(p, l2info.length) != 0) /* PPPoA vcmux encaps ? */
708 return l2info.header_len;
710 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
711 return l2info.header_len;
713 return l2info.header_len;
715 #endif
718 /* try to guess, based on all PPP protos that are supported in
719 * a juniper router if the payload data is encapsulated using PPP */
721 juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
723 switch(EXTRACT_16BITS(p)) {
724 case PPP_IP :
725 case PPP_OSI :
726 case PPP_MPLS_UCAST :
727 case PPP_MPLS_MCAST :
728 case PPP_IPCP :
729 case PPP_OSICP :
730 case PPP_MPLSCP :
731 case PPP_LCP :
732 case PPP_PAP :
733 case PPP_CHAP :
734 case PPP_ML :
735 #ifdef INET6
736 case PPP_IPV6 :
737 case PPP_IPV6CP :
738 #endif
739 ppp_print(p, length);
740 break;
742 default:
743 return 0; /* did not find a ppp header */
744 break;
746 return 1; /* we printed a ppp packet */
750 ip_heuristic_guess(register const u_char *p, u_int length) {
752 switch(p[0]) {
753 case 0x45:
754 case 0x46:
755 case 0x47:
756 case 0x48:
757 case 0x49:
758 case 0x4a:
759 case 0x4b:
760 case 0x4c:
761 case 0x4d:
762 case 0x4e:
763 case 0x4f:
764 ip_print(gndo, p, length);
765 break;
766 #ifdef INET6
767 case 0x60:
768 case 0x61:
769 case 0x62:
770 case 0x63:
771 case 0x64:
772 case 0x65:
773 case 0x66:
774 case 0x67:
775 case 0x68:
776 case 0x69:
777 case 0x6a:
778 case 0x6b:
779 case 0x6c:
780 case 0x6d:
781 case 0x6e:
782 case 0x6f:
783 ip6_print(p, length);
784 break;
785 #endif
786 default:
787 return 0; /* did not find a ip header */
788 break;
790 return 1; /* we printed an v4/v6 packet */
793 static int
794 juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) {
796 struct juniper_cookie_table_t *lp = juniper_cookie_table;
797 u_int idx, offset;
798 #ifdef DLT_JUNIPER_ATM2
799 u_int32_t control_word;
800 #endif
802 l2info->header_len = 0;
803 l2info->cookie_len = 0;
804 l2info->proto = 0;
807 l2info->length = h->len;
808 l2info->caplen = h->caplen;
809 l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
811 TCHECK2(p[0],4);
812 if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */
813 printf("no magic-number found!");
814 return 0;
817 if (eflag) /* print direction */
818 printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction));
820 /* extensions present ? - calculate how much bytes to skip */
821 if ((p[3] & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) {
822 offset = 6 + EXTRACT_16BITS(p+4);
823 if (eflag>1)
824 printf("ext-len %u, ",EXTRACT_16BITS(p+4));
825 } else
826 offset = 4;
828 if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
829 if (eflag)
830 printf("no-L2-hdr, ");
832 /* there is no link-layer present -
833 * perform the v4/v6 heuristics
834 * to figure out what it is
836 TCHECK2(p[offset+4],1);
837 if(ip_heuristic_guess(p+offset+4,l2info->length-(offset+4)) == 0)
838 printf("no IP-hdr found!");
840 l2info->header_len=offset+4;
841 return 0; /* stop parsing the output further */
844 l2info->header_len = offset;
845 p+=l2info->header_len;
846 l2info->length -= l2info->header_len;
847 l2info->caplen -= l2info->header_len;
849 /* search through the cookie table and copy values matching for our PIC type */
850 while (lp->s != NULL) {
851 if (lp->pictype == l2info->pictype) {
853 l2info->cookie_len += lp->cookie_len;
855 switch (p[0]) {
856 case LS_COOKIE_ID:
857 l2info->cookie_type = LS_COOKIE_ID;
858 l2info->cookie_len += 2;
859 break;
860 case AS_COOKIE_ID:
861 l2info->cookie_type = AS_COOKIE_ID;
862 l2info->cookie_len = 8;
863 break;
865 default:
866 l2info->bundle = l2info->cookie[0];
867 break;
871 #ifdef DLT_JUNIPER_MFR
872 /* MFR child links don't carry cookies */
873 if (l2info->pictype == DLT_JUNIPER_MFR &&
874 (p[0] & MFR_BE_MASK) == MFR_BE_MASK) {
875 l2info->cookie_len = 0;
877 #endif
879 l2info->header_len += l2info->cookie_len;
880 l2info->length -= l2info->cookie_len;
881 l2info->caplen -= l2info->cookie_len;
883 if (eflag)
884 printf("%s-PIC, cookie-len %u",
885 lp->s,
886 l2info->cookie_len);
888 if (l2info->cookie_len > 0) {
889 TCHECK2(p[0],l2info->cookie_len);
890 if (eflag)
891 printf(", cookie 0x");
892 for (idx = 0; idx < l2info->cookie_len; idx++) {
893 l2info->cookie[idx] = p[idx]; /* copy cookie data */
894 if (eflag) printf("%02x",p[idx]);
898 if (eflag) printf(": "); /* print demarc b/w L2/L3*/
901 l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len);
902 break;
904 ++lp;
906 p+=l2info->cookie_len;
908 /* DLT_ specific parsing */
909 switch(l2info->pictype) {
910 #ifdef DLT_JUNIPER_MLPPP
911 case DLT_JUNIPER_MLPPP:
912 switch (l2info->cookie_type) {
913 case LS_COOKIE_ID:
914 l2info->bundle = l2info->cookie[1];
915 break;
916 case AS_COOKIE_ID:
917 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
918 l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
919 break;
920 default:
921 l2info->bundle = l2info->cookie[0];
922 break;
924 break;
925 #endif
926 #ifdef DLT_JUNIPER_MLFR
927 case DLT_JUNIPER_MLFR:
928 switch (l2info->cookie_type) {
929 case LS_COOKIE_ID:
930 l2info->bundle = l2info->cookie[1];
931 l2info->proto = EXTRACT_16BITS(p);
932 l2info->header_len += 2;
933 l2info->length -= 2;
934 l2info->caplen -= 2;
935 break;
936 case AS_COOKIE_ID:
937 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
938 l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
939 break;
940 default:
941 l2info->bundle = l2info->cookie[0];
942 l2info->header_len += 2;
943 l2info->length -= 2;
944 l2info->caplen -= 2;
945 break;
947 break;
948 #endif
949 #ifdef DLT_JUNIPER_MFR
950 case DLT_JUNIPER_MFR:
951 switch (l2info->cookie_type) {
952 case LS_COOKIE_ID:
953 l2info->bundle = l2info->cookie[1];
954 l2info->proto = EXTRACT_16BITS(p);
955 l2info->header_len += 2;
956 l2info->length -= 2;
957 l2info->caplen -= 2;
958 break;
959 case AS_COOKIE_ID:
960 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
961 l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
962 break;
963 default:
964 l2info->bundle = l2info->cookie[0];
965 break;
967 break;
968 #endif
969 #ifdef DLT_JUNIPER_ATM2
970 case DLT_JUNIPER_ATM2:
971 TCHECK2(p[0],4);
972 /* ATM cell relay control word present ? */
973 if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK) {
974 control_word = EXTRACT_32BITS(p);
975 /* some control word heuristics */
976 switch(control_word) {
977 case 0: /* zero control word */
978 case 0x08000000: /* < JUNOS 7.4 control-word */
979 case 0x08380000: /* cntl word plus cell length (56) >= JUNOS 7.4*/
980 l2info->header_len += 4;
981 break;
982 default:
983 break;
986 if (eflag)
987 printf("control-word 0x%08x ", control_word);
989 break;
990 #endif
991 #ifdef DLT_JUNIPER_ATM1
992 case DLT_JUNIPER_ATM1:
993 break;
994 #endif
995 #ifdef DLT_JUNIPER_PPP
996 case DLT_JUNIPER_PPP:
997 break;
998 #endif
999 #ifdef DLT_JUNIPER_CHDLC
1000 case DLT_JUNIPER_CHDLC:
1001 break;
1002 #endif
1003 #ifdef DLT_JUNIPER_ETHER
1004 case DLT_JUNIPER_ETHER:
1005 break;
1006 #endif
1007 #ifdef DLT_JUNIPER_FRELAY
1008 case DLT_JUNIPER_FRELAY:
1009 break;
1010 #endif
1012 default:
1013 printf("Unknown Juniper DLT_ type %u: ", l2info->pictype);
1014 break;
1017 if (eflag > 1)
1018 printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto);
1020 return 1; /* everything went ok so far. continue parsing */
1021 trunc:
1022 printf("[|juniper_hdr], length %u",h->len);
1023 return 0;
1028 * Local Variables:
1029 * c-style: whitesmith
1030 * c-basic-offset: 4
1031 * End: