Remove old versions of tcpdump.
[dragonfly.git] / contrib / tcpdump-3.9 / print-juniper.c
1 /* 
2  * Redistribution and use in source and binary forms, with or without
3  * modification, are permitted provided that: (1) source code
4  * distributions retain the above copyright notice and this paragraph
5  * in its entirety, and (2) distributions including binary code include
6  * the above copyright notice and this paragraph in its entirety in
7  * the documentation or other materials provided with the distribution.
8  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
10  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11  * FOR A PARTICULAR PURPOSE.
12  *
13  * Original code by Hannes Gredler (hannes@juniper.net)
14  */
15
16 #ifndef lint
17 static const char rcsid[] _U_ =
18     "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.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
62 static struct tok juniper_ipsec_type_values[] = {
63     { JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE, "ESP ENCR-AUTH" },
64     { JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE, "ESP ENCR-AH AUTH" },
65     { JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE, "ESP AUTH" },
66     { JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE, "AH AUTH" },
67     { JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE, "ESP ENCR" },
68     { 0, NULL}
69 };
70
71 static struct tok juniper_direction_values[] = {
72     { JUNIPER_BPF_IN,  "In"},
73     { JUNIPER_BPF_OUT, "Out"},
74     { 0, NULL}
75 };
76
77 struct juniper_cookie_table_t {
78     u_int32_t pictype;          /* pic type */
79     u_int8_t  cookie_len;       /* cookie len */
80     const char *s;              /* pic name */
81 };
82
83 static struct juniper_cookie_table_t juniper_cookie_table[] = {
84 #ifdef DLT_JUNIPER_ATM1
85     { DLT_JUNIPER_ATM1,  4, "ATM1"},
86 #endif
87 #ifdef DLT_JUNIPER_ATM2
88     { DLT_JUNIPER_ATM2,  8, "ATM2"},
89 #endif
90 #ifdef DLT_JUNIPER_MLPPP
91     { DLT_JUNIPER_MLPPP, 2, "MLPPP"},
92 #endif
93 #ifdef DLT_JUNIPER_MLFR
94     { DLT_JUNIPER_MLFR,  2, "MLFR"},
95 #endif
96 #ifdef DLT_JUNIPER_MFR
97     { DLT_JUNIPER_MFR,   4, "MFR"},
98 #endif
99 #ifdef DLT_JUNIPER_PPPOE
100     { DLT_JUNIPER_PPPOE, 0, "PPPoE"},
101 #endif
102 #ifdef DLT_JUNIPER_PPPOE_ATM
103     { DLT_JUNIPER_PPPOE_ATM, 0, "PPPoE ATM"},
104 #endif
105 #ifdef DLT_JUNIPER_GGSN
106     { DLT_JUNIPER_GGSN, 8, "GGSN"},
107 #endif
108 #ifdef DLT_JUNIPER_MONITOR
109     { DLT_JUNIPER_MONITOR, 8, "MONITOR"},
110 #endif
111 #ifdef DLT_JUNIPER_SERVICES
112     { DLT_JUNIPER_SERVICES, 8, "AS"},
113 #endif
114 #ifdef DLT_JUNIPER_ES
115     { DLT_JUNIPER_ES, 0, "ES"},
116 #endif
117     { 0, 0, NULL }
118 };
119
120 struct juniper_l2info_t {
121     u_int32_t length;
122     u_int32_t caplen;
123     u_int32_t pictype;
124     u_int8_t direction;
125     u_int8_t header_len;
126     u_int8_t cookie_len;
127     u_int8_t cookie_type;
128     u_int8_t cookie[8];
129     u_int8_t bundle;
130     u_int16_t proto;
131 };
132
133 #define LS_COOKIE_ID            0x54
134 #define AS_COOKIE_ID            0x47
135 #define LS_MLFR_COOKIE_LEN      4
136 #define ML_MLFR_COOKIE_LEN      2
137 #define LS_MFR_COOKIE_LEN       6
138 #define ATM1_COOKIE_LEN         4
139 #define ATM2_COOKIE_LEN         8
140
141 #define ATM2_PKT_TYPE_MASK  0x70
142 #define ATM2_GAP_COUNT_MASK 0x3F
143
144 #define JUNIPER_PROTO_NULL          1
145 #define JUNIPER_PROTO_IPV4          2
146 #define JUNIPER_PROTO_IPV6          6
147
148 #define MFR_BE_MASK 0xc0
149
150 static struct tok juniper_protocol_values[] = {
151     { JUNIPER_PROTO_NULL, "Null" },
152     { JUNIPER_PROTO_IPV4, "IPv4" },
153     { JUNIPER_PROTO_IPV6, "IPv6" },
154     { 0, NULL}
155 };
156
157 int ip_heuristic_guess(register const u_char *, u_int);
158 int juniper_ppp_heuristic_guess(register const u_char *, u_int);
159 static int juniper_parse_header (const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
160
161 #ifdef DLT_JUNIPER_GGSN
162 u_int
163 juniper_ggsn_print(const struct pcap_pkthdr *h, register const u_char *p)
164 {
165         struct juniper_l2info_t l2info;
166         struct juniper_ggsn_header {
167             u_int8_t svc_id;
168             u_int8_t flags_len;
169             u_int8_t proto;
170             u_int8_t flags;
171             u_int8_t vlan_id[2];
172             u_int8_t res[2];
173         };
174         const struct juniper_ggsn_header *gh;
175
176         l2info.pictype = DLT_JUNIPER_GGSN;
177         if(juniper_parse_header(p, h, &l2info) == 0)
178             return l2info.header_len;
179
180         p+=l2info.header_len;
181         gh = (struct juniper_ggsn_header *)p;
182
183         if (eflag)
184             printf("proto %s (%u), vlan %u: ",
185                    tok2str(juniper_protocol_values,"Unknown",gh->proto),
186                    gh->proto,
187                    EXTRACT_16BITS(&gh->vlan_id[0]));
188
189         switch (gh->proto) {
190         case JUNIPER_PROTO_IPV4:
191             ip_print(gndo, p, l2info.length);
192             break;
193 #ifdef INET6
194         case JUNIPER_PROTO_IPV6:
195             ip6_print(p, l2info.length);
196             break;
197 #endif /* INET6 */
198         default:
199             if (!eflag)
200                 printf("unknown GGSN proto (%u)", gh->proto);
201         }
202
203         return l2info.header_len;
204 }
205 #endif
206
207 #ifdef DLT_JUNIPER_ES
208 u_int
209 juniper_es_print(const struct pcap_pkthdr *h, register const u_char *p)
210 {
211         struct juniper_l2info_t l2info;
212         struct juniper_ipsec_header {
213             u_int8_t sa_index[2];
214             u_int8_t ttl;
215             u_int8_t type;
216             u_int8_t spi[4];
217             u_int8_t src_ip[4];
218             u_int8_t dst_ip[4];
219         };
220         u_int rewrite_len,es_type_bundle;
221         const struct juniper_ipsec_header *ih;
222
223         l2info.pictype = DLT_JUNIPER_ES;
224         if(juniper_parse_header(p, h, &l2info) == 0)
225             return l2info.header_len;
226
227         p+=l2info.header_len;
228         ih = (struct juniper_ipsec_header *)p;
229
230         switch (ih->type) {
231         case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE:
232         case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE:
233             rewrite_len = 0;
234             es_type_bundle = 1;
235             break;
236         case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE:
237         case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE:
238         case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE:
239             rewrite_len = 16;
240             es_type_bundle = 0;
241         default:
242             printf("ES Invalid type %u, length %u",
243                    ih->type,
244                    l2info.length);
245             return l2info.header_len;
246         }
247
248         l2info.length-=rewrite_len;
249         p+=rewrite_len;
250
251         if (eflag) {
252             if (!es_type_bundle) {
253                 printf("ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n", 
254                        EXTRACT_16BITS(&ih->sa_index),
255                        ih->ttl, 
256                        tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
257                        ih->type,
258                        EXTRACT_32BITS(&ih->spi),
259                        ipaddr_string(EXTRACT_32BITS(&ih->src_ip)),
260                        ipaddr_string(EXTRACT_32BITS(&ih->dst_ip)),
261                        l2info.length);
262             } else {
263                 printf("ES SA, index %u, ttl %u type %s (%u), length %u\n", 
264                        EXTRACT_16BITS(&ih->sa_index),
265                        ih->ttl, 
266                        tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
267                        ih->type,
268                        l2info.length);
269             }
270         }
271
272         ip_print(gndo, p, l2info.length);
273         return l2info.header_len;
274 }
275 #endif
276
277 #ifdef DLT_JUNIPER_MONITOR
278 u_int
279 juniper_monitor_print(const struct pcap_pkthdr *h, register const u_char *p)
280 {
281         struct juniper_l2info_t l2info;
282         struct juniper_monitor_header {
283             u_int8_t pkt_type;
284             u_int8_t padding;
285             u_int8_t iif[2];
286             u_int8_t service_id[4];
287         };
288         const struct juniper_monitor_header *mh;
289
290         l2info.pictype = DLT_JUNIPER_MONITOR;
291         if(juniper_parse_header(p, h, &l2info) == 0)
292             return l2info.header_len;
293
294         p+=l2info.header_len;
295         mh = (struct juniper_monitor_header *)p;
296
297         if (eflag)
298             printf("service-id %u, iif %u, pkt-type %u: ",
299                    EXTRACT_32BITS(&mh->service_id),
300                    EXTRACT_16BITS(&mh->iif),
301                    mh->pkt_type);
302
303         /* no proto field - lets guess by first byte of IP header*/
304         ip_heuristic_guess(p, l2info.length);
305
306         return l2info.header_len;
307 }
308 #endif
309
310 #ifdef DLT_JUNIPER_SERVICES
311 u_int
312 juniper_services_print(const struct pcap_pkthdr *h, register const u_char *p)
313 {
314         struct juniper_l2info_t l2info;
315         struct juniper_services_header {
316             u_int8_t svc_id;
317             u_int8_t flags_len;
318             u_int8_t svc_set_id[2];
319             u_int8_t dir_iif[4];
320         };
321         const struct juniper_services_header *sh;
322
323         l2info.pictype = DLT_JUNIPER_SERVICES;
324         if(juniper_parse_header(p, h, &l2info) == 0)
325             return l2info.header_len;
326
327         p+=l2info.header_len;
328         sh = (struct juniper_services_header *)p;
329
330         if (eflag)
331             printf("service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ",
332                    sh->svc_id,
333                    sh->flags_len,
334                    EXTRACT_16BITS(&sh->svc_set_id),
335                    EXTRACT_24BITS(&sh->dir_iif[1]));
336
337         /* no proto field - lets guess by first byte of IP header*/
338         ip_heuristic_guess(p, l2info.length);
339
340         return l2info.header_len;
341 }
342 #endif
343
344 #ifdef DLT_JUNIPER_PPPOE
345 u_int
346 juniper_pppoe_print(const struct pcap_pkthdr *h, register const u_char *p)
347 {
348         struct juniper_l2info_t l2info;
349
350         l2info.pictype = DLT_JUNIPER_PPPOE;
351         if(juniper_parse_header(p, h, &l2info) == 0)
352             return l2info.header_len;
353
354         p+=l2info.header_len;
355         /* this DLT contains nothing but raw ethernet frames */
356         ether_print(p, l2info.length, l2info.caplen);
357         return l2info.header_len;
358 }
359 #endif
360
361 #ifdef DLT_JUNIPER_ETHER
362 u_int
363 juniper_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
379 u_int
380 juniper_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
396 u_int
397 juniper_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
413 u_int
414 juniper_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
430 u_int
431 juniper_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
458 u_int
459 juniper_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
519 u_int
520 juniper_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
580 u_int
581 juniper_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
621 u_int
622 juniper_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
669 u_int
670 juniper_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 */
720 int
721 juniper_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
749 int
750 ip_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
793 static int
794 juniper_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  */