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 */
1033