Move tcpdump-3.9/ to tcpdump/. No need for a versioned dir.
[dragonfly.git] / contrib / tcpdump / print-juniper.c
CommitLineData
c8cf0f94
PA
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.22 2006/05/10 22:42:46 guy Exp $ (LBL)";
19#endif
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include <tcpdump-stdinc.h>
26
27#include <pcap.h>
28#include <stdio.h>
29
30#include "interface.h"
31#include "addrtoname.h"
32#include "extract.h"
33#include "ppp.h"
34#include "llc.h"
35#include "nlpid.h"
36#include "ethertype.h"
37#include "atm.h"
38
39#define JUNIPER_BPF_OUT 0 /* Outgoing packet */
40#define JUNIPER_BPF_IN 1 /* Incoming packet */
41#define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */
42#define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */
43#define JUNIPER_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
62static 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
71static struct tok juniper_direction_values[] = {
72 { JUNIPER_BPF_IN, "In"},
73 { JUNIPER_BPF_OUT, "Out"},
74 { 0, NULL}
75};
76
77struct 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
83static 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
120struct 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
150static 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
157int ip_heuristic_guess(register const u_char *, u_int);
158int juniper_ppp_heuristic_guess(register const u_char *, u_int);
159static int juniper_parse_header (const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
160
161#ifdef DLT_JUNIPER_GGSN
162u_int
163juniper_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
208u_int
209juniper_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
278u_int
279juniper_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
311u_int
312juniper_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
345u_int
346juniper_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_ETHER
362u_int
363juniper_ether_print(const struct pcap_pkthdr *h, register const u_char *p)
364{
365 struct juniper_l2info_t l2info;
366
367 l2info.pictype = DLT_JUNIPER_ETHER;
368 if(juniper_parse_header(p, h, &l2info) == 0)
369 return l2info.header_len;
370
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;
375}
376#endif
377
378#ifdef DLT_JUNIPER_PPP
379u_int
380juniper_ppp_print(const struct pcap_pkthdr *h, register const u_char *p)
381{
382 struct juniper_l2info_t l2info;
383
384 l2info.pictype = DLT_JUNIPER_PPP;
385 if(juniper_parse_header(p, h, &l2info) == 0)
386 return l2info.header_len;
387
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;
392}
393#endif
394
395#ifdef DLT_JUNIPER_FRELAY
396u_int
397juniper_frelay_print(const struct pcap_pkthdr *h, register const u_char *p)
398{
399 struct juniper_l2info_t l2info;
400
401 l2info.pictype = DLT_JUNIPER_FRELAY;
402 if(juniper_parse_header(p, h, &l2info) == 0)
403 return l2info.header_len;
404
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;
409}
410#endif
411
412#ifdef DLT_JUNIPER_CHDLC
413u_int
414juniper_chdlc_print(const struct pcap_pkthdr *h, register const u_char *p)
415{
416 struct juniper_l2info_t l2info;
417
418 l2info.pictype = DLT_JUNIPER_CHDLC;
419 if(juniper_parse_header(p, h, &l2info) == 0)
420 return l2info.header_len;
421
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;
426}
427#endif
428
429#ifdef DLT_JUNIPER_PPPOE_ATM
430u_int
431juniper_pppoe_atm_print(const struct pcap_pkthdr *h, register const u_char *p)
432{
433 struct juniper_l2info_t l2info;
434 u_int16_t extracted_ethertype;
435
436 l2info.pictype = DLT_JUNIPER_PPPOE_ATM;
437 if(juniper_parse_header(p, h, &l2info) == 0)
438 return l2info.header_len;
439
440 p+=l2info.header_len;
441
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);
452
453 return l2info.header_len;
454}
455#endif
456
457#ifdef DLT_JUNIPER_MLPPP
458u_int
459juniper_mlppp_print(const struct pcap_pkthdr *h, register const u_char *p)
460{
461 struct juniper_l2info_t l2info;
462
463 l2info.pictype = DLT_JUNIPER_MLPPP;
464 if(juniper_parse_header(p, h, &l2info) == 0)
465 return l2info.header_len;
466
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);
473
474 p+=l2info.header_len;
475
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
481 */
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;
500 }
501
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;
511 }
512
513 return l2info.header_len;
514}
515#endif
516
517
518#ifdef DLT_JUNIPER_MFR
519u_int
520juniper_mfr_print(const struct pcap_pkthdr *h, register const u_char *p)
521{
522 struct juniper_l2info_t l2info;
523
524 l2info.pictype = DLT_JUNIPER_MFR;
525 if(juniper_parse_header(p, h, &l2info) == 0)
526 return l2info.header_len;
527
528 p+=l2info.header_len;
529
530 /* child-link ? */
531 if (l2info.cookie_len == 0) {
532 mfr_print(p,l2info.length);
533 return l2info.header_len;
534 }
535
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;
555 }
556 return l2info.header_len;
557 }
558
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);
573 }
574
575 return l2info.header_len;
576}
577#endif
578
579#ifdef DLT_JUNIPER_MLFR
580u_int
581juniper_mlfr_print(const struct pcap_pkthdr *h, register const u_char *p)
582{
583 struct juniper_l2info_t l2info;
584
585 l2info.pictype = DLT_JUNIPER_MLFR;
586 if(juniper_parse_header(p, h, &l2info) == 0)
587 return l2info.header_len;
588
589 p+=l2info.header_len;
590
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);
606 }
607
608 return l2info.header_len;
609}
610#endif
611
612/*
613 * ATM1 PIC cookie format
614 *
615 * +-----+-------------------------+-------------------------------+
616 * |fmtid| vc index | channel ID |
617 * +-----+-------------------------+-------------------------------+
618 */
619
620#ifdef DLT_JUNIPER_ATM1
621u_int
622juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p)
623{
624 u_int16_t extracted_ethertype;
625
626 struct juniper_l2info_t l2info;
627
628 l2info.pictype = DLT_JUNIPER_ATM1;
629 if(juniper_parse_header(p, h, &l2info) == 0)
630 return l2info.header_len;
631
632 p+=l2info.header_len;
633
634 if (l2info.cookie[0] == 0x80) { /* OAM cell ? */
635 oam_print(p,l2info.length,ATM_OAM_NOHEC);
636 return l2info.header_len;
637 }
638
639 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
640 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
641
642 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
643 &extracted_ethertype) != 0)
644 return l2info.header_len;
645 }
646
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;
651 }
652
653 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
654 return l2info.header_len;
655
656 return l2info.header_len;
657}
658#endif
659
660/*
661 * ATM2 PIC cookie format
662 *
663 * +-------------------------------+---------+---+-----+-----------+
664 * | channel ID | reserv |AAL| CCRQ| gap cnt |
665 * +-------------------------------+---------+---+-----+-----------+
666 */
667
668#ifdef DLT_JUNIPER_ATM2
669u_int
670juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p)
671{
672 u_int16_t extracted_ethertype;
673
674 struct juniper_l2info_t l2info;
675
676 l2info.pictype = DLT_JUNIPER_ATM2;
677 if(juniper_parse_header(p, h, &l2info) == 0)
678 return l2info.header_len;
679
680 p+=l2info.header_len;
681
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;
685 }
686
687 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
688 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
689
690 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
691 &extracted_ethertype) != 0)
692 return l2info.header_len;
693 }
694
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;
699 }
700
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;
705 }
706
707 if(juniper_ppp_heuristic_guess(p, l2info.length) != 0) /* PPPoA vcmux encaps ? */
708 return l2info.header_len;
709
710 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
711 return l2info.header_len;
712
713 return l2info.header_len;
714}
715#endif
716
717
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 */
720int
721juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
722
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;
741
742 default:
743 return 0; /* did not find a ppp header */
744 break;
745 }
746 return 1; /* we printed a ppp packet */
747}
748
749int
750ip_heuristic_guess(register const u_char *p, u_int length) {
751
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;
789 }
790 return 1; /* we printed an v4/v6 packet */
791}
792
793static int
794juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) {
795
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
801
802 l2info->header_len = 0;
803 l2info->cookie_len = 0;
804 l2info->proto = 0;
805
806
807 l2info->length = h->len;
808 l2info->caplen = h->caplen;
809 l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
810
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;
815 }
816
817 if (eflag) /* print direction */
818 printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction));
819
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;
827
828 if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
829 if (eflag)
830 printf("no-L2-hdr, ");
831
832 /* there is no link-layer present -
833 * perform the v4/v6 heuristics
834 * to figure out what it is
835 */
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!");
839
840 l2info->header_len=offset+4;
841 return 0; /* stop parsing the output further */
842
843 }
844 l2info->header_len = offset;
845 p+=l2info->header_len;
846 l2info->length -= l2info->header_len;
847 l2info->caplen -= l2info->header_len;
848
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) {
852
853 l2info->cookie_len += lp->cookie_len;
854
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;
864
865 default:
866 l2info->bundle = l2info->cookie[0];
867 break;
868 }
869
870
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;
876 }
877#endif
878
879 l2info->header_len += l2info->cookie_len;
880 l2info->length -= l2info->cookie_len;
881 l2info->caplen -= l2info->cookie_len;
882
883 if (eflag)
884 printf("%s-PIC, cookie-len %u",
885 lp->s,
886 l2info->cookie_len);
887
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]);
895 }
896 }
897
898 if (eflag) printf(": "); /* print demarc b/w L2/L3*/
899
900
901 l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len);
902 break;
903 }
904 ++lp;
905 }
906 p+=l2info->cookie_len;
907
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;
923 }
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;
946 }
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;
966 }
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;
984 }
985
986 if (eflag)
987 printf("control-word 0x%08x ", control_word);
988 }
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
1011
1012 default:
1013 printf("Unknown Juniper DLT_ type %u: ", l2info->pictype);
1014 break;
1015 }
1016
1017 if (eflag > 1)
1018 printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto);
1019
1020 return 1; /* everything went ok so far. continue parsing */
1021 trunc:
1022 printf("[|juniper_hdr], length %u",h->len);
1023 return 0;
1024}
1025
1026
1027/*
1028 * Local Variables:
1029 * c-style: whitesmith
1030 * c-basic-offset: 4
1031 * End:
1032 */