print-juniper.c revision 147899
1218885Sdim/*
2218885Sdim * Redistribution and use in source and binary forms, with or without
3218885Sdim * modification, are permitted provided that: (1) source code
4218885Sdim * distributions retain the above copyright notice and this paragraph
5218885Sdim * in its entirety, and (2) distributions including binary code include
6218885Sdim * the above copyright notice and this paragraph in its entirety in
7218885Sdim * the documentation or other materials provided with the distribution.
8218885Sdim * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9218885Sdim * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
10218885Sdim * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11218885Sdim * FOR A PARTICULAR PURPOSE.
12218885Sdim *
13218885Sdim * Original code by Hannes Gredler (hannes@juniper.net)
14218885Sdim */
15218885Sdim
16218885Sdim#ifndef lint
17218885Sdimstatic const char rcsid[] _U_ =
18218885Sdim    "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.8.2.13 2005/06/20 07:45:05 hannes Exp $ (LBL)";
19218885Sdim#endif
20218885Sdim
21218885Sdim#ifdef HAVE_CONFIG_H
22218885Sdim#include "config.h"
23218885Sdim#endif
24218885Sdim
25218885Sdim#include <tcpdump-stdinc.h>
26218885Sdim
27218885Sdim#include <pcap.h>
28218885Sdim#include <stdio.h>
29218885Sdim
30218885Sdim#include "interface.h"
31218885Sdim#include "addrtoname.h"
32218885Sdim#include "extract.h"
33218885Sdim#include "ppp.h"
34249423Sdim#include "llc.h"
35249423Sdim#include "nlpid.h"
36249423Sdim#include "ethertype.h"
37249423Sdim#include "atm.h"
38234353Sdim
39234353Sdim#define JUNIPER_BPF_OUT           0       /* Outgoing packet */
40234353Sdim#define JUNIPER_BPF_IN            1       /* Incoming packet */
41234353Sdim#define JUNIPER_BPF_PKT_IN        0x1     /* Incoming packet */
42218885Sdim#define JUNIPER_BPF_NO_L2         0x2     /* L2 header stripped */
43218885Sdim#define JUNIPER_MGC_NUMBER        0x4d4743 /* = "MGC" */
44218885Sdim
45218885Sdim#define JUNIPER_LSQ_L3_PROTO_SHIFT     4
46218885Sdim#define JUNIPER_LSQ_L3_PROTO_MASK     (0x17 << JUNIPER_LSQ_L3_PROTO_SHIFT)
47218885Sdim#define JUNIPER_LSQ_L3_PROTO_IPV4     (0 << JUNIPER_LSQ_L3_PROTO_SHIFT)
48218885Sdim#define JUNIPER_LSQ_L3_PROTO_IPV6     (1 << JUNIPER_LSQ_L3_PROTO_SHIFT)
49218885Sdim#define JUNIPER_LSQ_L3_PROTO_MPLS     (2 << JUNIPER_LSQ_L3_PROTO_SHIFT)
50218885Sdim#define JUNIPER_LSQ_L3_PROTO_ISO      (3 << JUNIPER_LSQ_L3_PROTO_SHIFT)
51218885Sdim
52218885Sdim#define JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE 1
53218885Sdim#define JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE 2
54218885Sdim#define JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE 3
55218885Sdim#define JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE 4
56218885Sdim#define JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE 5
57218885Sdim
58218885Sdimstatic struct tok juniper_ipsec_type_values[] = {
59218885Sdim    { JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE, "ESP ENCR-AUTH" },
60218885Sdim    { JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE, "ESP ENCR-AH AUTH" },
61218885Sdim    { JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE, "ESP AUTH" },
62218885Sdim    { JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE, "AH AUTH" },
63218885Sdim    { JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE, "ESP ENCR" },
64218885Sdim    { 0, NULL}
65218885Sdim};
66218885Sdim
67218885Sdimstatic struct tok juniper_direction_values[] = {
68218885Sdim    { JUNIPER_BPF_IN,  "In"},
69218885Sdim    { JUNIPER_BPF_OUT, "Out"},
70218885Sdim    { 0, NULL}
71218885Sdim};
72218885Sdim
73263508Sdimstruct juniper_cookie_table_t {
74243830Sdim    u_int32_t pictype;		/* pic type */
75218885Sdim    u_int8_t  cookie_len;       /* cookie len */
76263508Sdim    const char *s;		/* pic name */
77249423Sdim};
78218885Sdim
79226633Sdimstatic struct juniper_cookie_table_t juniper_cookie_table[] = {
80239462Sdim#ifdef DLT_JUNIPER_ATM1
81234353Sdim    { DLT_JUNIPER_ATM1,  4, "ATM1"},
82223017Sdim#endif
83218885Sdim#ifdef DLT_JUNIPER_ATM2
84249423Sdim    { DLT_JUNIPER_ATM2,  8, "ATM2"},
85249423Sdim#endif
86218885Sdim#ifdef DLT_JUNIPER_MLPPP
87218885Sdim    { DLT_JUNIPER_MLPPP, 2, "MLPPP"},
88218885Sdim#endif
89218885Sdim#ifdef DLT_JUNIPER_MLFR
90263508Sdim    { DLT_JUNIPER_MLFR,  2, "MLFR"},
91263508Sdim#endif
92218885Sdim#ifdef DLT_JUNIPER_MFR
93218885Sdim    { DLT_JUNIPER_MFR,   4, "MFR"},
94218885Sdim#endif
95218885Sdim#ifdef DLT_JUNIPER_PPPOE
96234353Sdim    { DLT_JUNIPER_PPPOE, 0, "PPPoE"},
97243830Sdim#endif
98218885Sdim#ifdef DLT_JUNIPER_PPPOE_ATM
99218885Sdim    { DLT_JUNIPER_PPPOE_ATM, 0, "PPPoE ATM"},
100218885Sdim#endif
101218885Sdim#ifdef DLT_JUNIPER_GGSN
102218885Sdim    { DLT_JUNIPER_GGSN, 8, "GGSN"},
103263508Sdim#endif
104218885Sdim#ifdef DLT_JUNIPER_MONITOR
105218885Sdim    { DLT_JUNIPER_MONITOR, 8, "MONITOR"},
106263508Sdim#endif
107243830Sdim#ifdef DLT_JUNIPER_SERVICES
108218885Sdim    { DLT_JUNIPER_SERVICES, 8, "AS"},
109218885Sdim#endif
110218885Sdim#ifdef DLT_JUNIPER_ES
111218885Sdim    { DLT_JUNIPER_ES, 0, "ES"},
112218885Sdim#endif
113218885Sdim    { 0, 0, NULL }
114239462Sdim};
115218885Sdim
116234353Sdimstruct juniper_l2info_t {
117221345Sdim    u_int32_t length;
118234353Sdim    u_int32_t caplen;
119249423Sdim    u_int32_t pictype;
120249423Sdim    u_int8_t direction;
121234353Sdim    u_int8_t header_len;
122263508Sdim    u_int8_t cookie_len;
123218885Sdim    u_int8_t cookie_type;
124218885Sdim    u_int8_t cookie[8];
125218885Sdim    u_int8_t bundle;
126218885Sdim    u_int16_t proto;
127234353Sdim};
128218885Sdim
129218885Sdim#define LS_COOKIE_ID            0x54
130218885Sdim#define AS_COOKIE_ID            0x47
131218885Sdim#define LS_MLFR_COOKIE_LEN	4
132218885Sdim#define ML_MLFR_COOKIE_LEN	2
133218885Sdim#define LS_MFR_COOKIE_LEN	6
134218885Sdim#define ATM1_COOKIE_LEN         4
135218885Sdim#define ATM2_COOKIE_LEN         8
136218885Sdim
137218885Sdim#define ATM2_PKT_TYPE_MASK  0x70
138249423Sdim#define ATM2_GAP_COUNT_MASK 0x3F
139218885Sdim
140218885Sdim#define JUNIPER_PROTO_NULL          1
141218885Sdim#define JUNIPER_PROTO_IPV4          2
142218885Sdim#define JUNIPER_PROTO_IPV6          6
143218885Sdim
144218885Sdimstatic struct tok juniper_protocol_values[] = {
145218885Sdim    { JUNIPER_PROTO_NULL, "Null" },
146218885Sdim    { JUNIPER_PROTO_IPV4, "IPv4" },
147218885Sdim    { JUNIPER_PROTO_IPV6, "IPv6" },
148218885Sdim    { 0, NULL}
149218885Sdim};
150218885Sdim
151218885Sdimint ip_heuristic_guess(register const u_char *, u_int);
152239462Sdimint juniper_ppp_heuristic_guess(register const u_char *, u_int);
153218885Sdimstatic int juniper_parse_header (const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
154218885Sdim
155218885Sdim#ifdef DLT_JUNIPER_GGSN
156234353Sdimu_int
157218885Sdimjuniper_ggsn_print(const struct pcap_pkthdr *h, register const u_char *p)
158218885Sdim{
159218885Sdim        struct juniper_l2info_t l2info;
160218885Sdim        struct juniper_ggsn_header {
161218885Sdim            u_int8_t svc_id;
162218885Sdim            u_int8_t flags_len;
163218885Sdim            u_int8_t proto;
164234353Sdim            u_int8_t flags;
165263508Sdim            u_int8_t vlan_id[2];
166218885Sdim            u_int8_t res[2];
167218885Sdim        };
168218885Sdim        const struct juniper_ggsn_header *gh;
169218885Sdim
170224145Sdim        l2info.pictype = DLT_JUNIPER_GGSN;
171218885Sdim        if(juniper_parse_header(p, h, &l2info) == 0)
172218885Sdim            return l2info.header_len;
173218885Sdim
174226633Sdim        p+=l2info.header_len;
175234353Sdim        gh = (struct juniper_ggsn_header *)p;
176234353Sdim
177224145Sdim        if (eflag)
178218885Sdim            printf("proto %s (%u), vlan %u: ",
179218885Sdim                   tok2str(juniper_protocol_values,"Unknown",gh->proto),
180243830Sdim                   gh->proto,
181218885Sdim                   EXTRACT_16BITS(&gh->vlan_id[0]));
182218885Sdim
183218885Sdim        switch (gh->proto) {
184234353Sdim        case JUNIPER_PROTO_IPV4:
185218885Sdim            ip_print(gndo, p, l2info.length);
186239462Sdim            break;
187218885Sdim#ifdef INET6
188218885Sdim        case JUNIPER_PROTO_IPV6:
189218885Sdim            ip6_print(p, l2info.length);
190218885Sdim            break;
191243830Sdim#endif /* INET6 */
192218885Sdim        default:
193218885Sdim            if (!eflag)
194218885Sdim                printf("unknown GGSN proto (%u)", gh->proto);
195224145Sdim        }
196234353Sdim
197224145Sdim        return l2info.header_len;
198224145Sdim}
199224145Sdim#endif
200218885Sdim
201263508Sdim#ifdef DLT_JUNIPER_ES
202218885Sdimu_int
203218885Sdimjuniper_es_print(const struct pcap_pkthdr *h, register const u_char *p)
204218885Sdim{
205218885Sdim        struct juniper_l2info_t l2info;
206218885Sdim        struct juniper_ipsec_header {
207218885Sdim            u_int8_t sa_index[2];
208218885Sdim            u_int8_t ttl;
209218885Sdim            u_int8_t type;
210218885Sdim            u_int8_t spi[4];
211234353Sdim            u_int8_t src_ip[4];
212218885Sdim            u_int8_t dst_ip[4];
213218885Sdim        };
214218885Sdim        u_int rewrite_len,es_type_bundle;
215249423Sdim        const struct juniper_ipsec_header *ih;
216218885Sdim
217218885Sdim        l2info.pictype = DLT_JUNIPER_ES;
218218885Sdim        if(juniper_parse_header(p, h, &l2info) == 0)
219218885Sdim            return l2info.header_len;
220218885Sdim
221218885Sdim        p+=l2info.header_len;
222218885Sdim        ih = (struct juniper_ipsec_header *)p;
223218885Sdim
224218885Sdim        switch (ih->type) {
225218885Sdim        case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE:
226218885Sdim        case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE:
227243830Sdim            rewrite_len = 0;
228218885Sdim            es_type_bundle = 1;
229218885Sdim            break;
230218885Sdim        case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE:
231218885Sdim        case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE:
232218885Sdim        case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE:
233224145Sdim            rewrite_len = 16;
234218885Sdim            es_type_bundle = 0;
235218885Sdim        default:
236218885Sdim            printf("ES Invalid type %u, length %u",
237218885Sdim                   ih->type,
238218885Sdim                   l2info.length);
239243830Sdim            return l2info.header_len;
240218885Sdim        }
241218885Sdim
242218885Sdim        l2info.length-=rewrite_len;
243218885Sdim        p+=rewrite_len;
244218885Sdim
245218885Sdim        if (eflag) {
246218885Sdim            if (!es_type_bundle) {
247234353Sdim                printf("ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n",
248234353Sdim                       EXTRACT_16BITS(&ih->sa_index),
249243830Sdim                       ih->ttl,
250249423Sdim                       tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
251249423Sdim                       ih->type,
252218885Sdim                       EXTRACT_32BITS(&ih->spi),
253218885Sdim                       ipaddr_string(EXTRACT_32BITS(&ih->src_ip)),
254218885Sdim                       ipaddr_string(EXTRACT_32BITS(&ih->dst_ip)),
255218885Sdim                       l2info.length);
256218885Sdim            } else {
257218885Sdim                printf("ES SA, index %u, ttl %u type %s (%u), length %u\n",
258218885Sdim                       EXTRACT_16BITS(&ih->sa_index),
259218885Sdim                       ih->ttl,
260239462Sdim                       tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
261218885Sdim                       ih->type,
262234353Sdim                       l2info.length);
263234353Sdim            }
264243830Sdim        }
265251662Sdim
266234353Sdim        ip_print(gndo, p, l2info.length);
267239462Sdim        return l2info.header_len;
268218885Sdim}
269218885Sdim#endif
270218885Sdim
271#ifdef DLT_JUNIPER_MONITOR
272u_int
273juniper_monitor_print(const struct pcap_pkthdr *h, register const u_char *p)
274{
275        struct juniper_l2info_t l2info;
276        struct juniper_monitor_header {
277            u_int8_t pkt_type;
278            u_int8_t padding;
279            u_int8_t iif[2];
280            u_int8_t service_id[4];
281        };
282        const struct juniper_monitor_header *mh;
283
284        l2info.pictype = DLT_JUNIPER_MONITOR;
285        if(juniper_parse_header(p, h, &l2info) == 0)
286            return l2info.header_len;
287
288        p+=l2info.header_len;
289        mh = (struct juniper_monitor_header *)p;
290
291        if (eflag)
292            printf("service-id %u, iif %u, pkt-type %u: ",
293                   EXTRACT_32BITS(&mh->service_id),
294                   EXTRACT_16BITS(&mh->iif),
295                   mh->pkt_type);
296
297        /* no proto field - lets guess by first byte of IP header*/
298        ip_heuristic_guess(p, l2info.length);
299
300        return l2info.header_len;
301}
302#endif
303
304#ifdef DLT_JUNIPER_SERVICES
305u_int
306juniper_services_print(const struct pcap_pkthdr *h, register const u_char *p)
307{
308        struct juniper_l2info_t l2info;
309        struct juniper_services_header {
310            u_int8_t svc_id;
311            u_int8_t flags_len;
312            u_int8_t svc_set_id[2];
313            u_int8_t dir_iif[4];
314        };
315        const struct juniper_services_header *sh;
316
317        l2info.pictype = DLT_JUNIPER_SERVICES;
318        if(juniper_parse_header(p, h, &l2info) == 0)
319            return l2info.header_len;
320
321        p+=l2info.header_len;
322        sh = (struct juniper_services_header *)p;
323
324        if (eflag)
325            printf("service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ",
326                   sh->svc_id,
327                   sh->flags_len,
328                   EXTRACT_16BITS(&sh->svc_set_id),
329                   EXTRACT_24BITS(&sh->dir_iif[1]));
330
331        /* no proto field - lets guess by first byte of IP header*/
332        ip_heuristic_guess(p, l2info.length);
333
334        return l2info.header_len;
335}
336#endif
337
338#ifdef DLT_JUNIPER_PPPOE
339u_int
340juniper_pppoe_print(const struct pcap_pkthdr *h, register const u_char *p)
341{
342        struct juniper_l2info_t l2info;
343
344        l2info.pictype = DLT_JUNIPER_PPPOE;
345        if(juniper_parse_header(p, h, &l2info) == 0)
346            return l2info.header_len;
347
348        p+=l2info.header_len;
349        /* this DLT contains nothing but raw ethernet frames */
350        ether_print(p, l2info.length, l2info.caplen);
351        return l2info.header_len;
352}
353#endif
354
355#ifdef DLT_JUNIPER_PPPOE_ATM
356u_int
357juniper_pppoe_atm_print(const struct pcap_pkthdr *h, register const u_char *p)
358{
359        struct juniper_l2info_t l2info;
360	u_int16_t extracted_ethertype;
361
362        l2info.pictype = DLT_JUNIPER_PPPOE_ATM;
363        if(juniper_parse_header(p, h, &l2info) == 0)
364            return l2info.header_len;
365
366        p+=l2info.header_len;
367
368        extracted_ethertype = EXTRACT_16BITS(p);
369        /* this DLT contains nothing but raw PPPoE frames,
370         * prepended with a type field*/
371        if (ether_encap_print(extracted_ethertype,
372                              p+ETHERTYPE_LEN,
373                              l2info.length-ETHERTYPE_LEN,
374                              l2info.caplen-ETHERTYPE_LEN,
375                              &extracted_ethertype) == 0)
376            /* ether_type not known, probably it wasn't one */
377            printf("unknown ethertype 0x%04x", extracted_ethertype);
378
379        return l2info.header_len;
380}
381#endif
382
383#ifdef DLT_JUNIPER_MLPPP
384u_int
385juniper_mlppp_print(const struct pcap_pkthdr *h, register const u_char *p)
386{
387        struct juniper_l2info_t l2info;
388
389        l2info.pictype = DLT_JUNIPER_MLPPP;
390        if(juniper_parse_header(p, h, &l2info) == 0)
391            return l2info.header_len;
392
393        /* suppress Bundle-ID if frame was captured on a child-link
394         * best indicator if the cookie looks like a proto */
395        if (eflag &&
396            EXTRACT_16BITS(&l2info.cookie) != PPP_OSI &&
397            EXTRACT_16BITS(&l2info.cookie) !=  (PPP_ADDRESS << 8 | PPP_CONTROL))
398            printf("Bundle-ID %u: ",l2info.bundle);
399
400        p+=l2info.header_len;
401
402        /* first try the LSQ protos */
403        switch(l2info.proto) {
404        case JUNIPER_LSQ_L3_PROTO_IPV4:
405            ip_print(gndo, p, l2info.length);
406            return l2info.header_len;
407#ifdef INET6
408        case JUNIPER_LSQ_L3_PROTO_IPV6:
409            ip6_print(p,l2info.length);
410            return l2info.header_len;
411#endif
412        case JUNIPER_LSQ_L3_PROTO_MPLS:
413            mpls_print(p,l2info.length);
414            return l2info.header_len;
415        case JUNIPER_LSQ_L3_PROTO_ISO:
416            isoclns_print(p,l2info.length,l2info.caplen);
417            return l2info.header_len;
418        default:
419            break;
420        }
421
422        /* zero length cookie ? */
423        switch (EXTRACT_16BITS(&l2info.cookie)) {
424        case PPP_OSI:
425            ppp_print(p-2,l2info.length+2);
426            break;
427        case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */
428        default:
429            ppp_print(p,l2info.length);
430            break;
431        }
432
433        return l2info.header_len;
434}
435#endif
436
437
438#ifdef DLT_JUNIPER_MFR
439u_int
440juniper_mfr_print(const struct pcap_pkthdr *h, register const u_char *p)
441{
442        struct juniper_l2info_t l2info;
443
444        l2info.pictype = DLT_JUNIPER_MFR;
445        if(juniper_parse_header(p, h, &l2info) == 0)
446            return l2info.header_len;
447
448        p+=l2info.header_len;
449        /* suppress Bundle-ID if frame was captured on a child-link */
450        if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
451        switch (l2info.proto) {
452        case (LLCSAP_ISONS<<8 | LLCSAP_ISONS):
453            isoclns_print(p+1, l2info.length-1, l2info.caplen-1);
454            break;
455        case (LLC_UI<<8 | NLPID_Q933):
456        case (LLC_UI<<8 | NLPID_IP):
457        case (LLC_UI<<8 | NLPID_IP6):
458            /* pass IP{4,6} to the OSI layer for proper link-layer printing */
459            isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
460            break;
461        default:
462            printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
463        }
464
465        return l2info.header_len;
466}
467#endif
468
469#ifdef DLT_JUNIPER_MLFR
470u_int
471juniper_mlfr_print(const struct pcap_pkthdr *h, register const u_char *p)
472{
473        struct juniper_l2info_t l2info;
474
475        l2info.pictype = DLT_JUNIPER_MLFR;
476        if(juniper_parse_header(p, h, &l2info) == 0)
477            return l2info.header_len;
478
479        p+=l2info.header_len;
480
481        /* suppress Bundle-ID if frame was captured on a child-link */
482        if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
483        switch (l2info.proto) {
484        case (LLC_UI):
485        case (LLC_UI<<8):
486            isoclns_print(p, l2info.length, l2info.caplen);
487            break;
488        case (LLC_UI<<8 | NLPID_Q933):
489        case (LLC_UI<<8 | NLPID_IP):
490        case (LLC_UI<<8 | NLPID_IP6):
491            /* pass IP{4,6} to the OSI layer for proper link-layer printing */
492            isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
493            break;
494        default:
495            printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
496        }
497
498        return l2info.header_len;
499}
500#endif
501
502/*
503 *     ATM1 PIC cookie format
504 *
505 *     +-----+-------------------------+-------------------------------+
506 *     |fmtid|     vc index            |  channel  ID                  |
507 *     +-----+-------------------------+-------------------------------+
508 */
509
510#ifdef DLT_JUNIPER_ATM1
511u_int
512juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p)
513{
514        u_int16_t extracted_ethertype;
515
516        struct juniper_l2info_t l2info;
517
518        l2info.pictype = DLT_JUNIPER_ATM1;
519        if(juniper_parse_header(p, h, &l2info) == 0)
520            return l2info.header_len;
521
522        p+=l2info.header_len;
523
524        if (l2info.cookie[0] == 0x80) { /* OAM cell ? */
525            oam_print(p,l2info.length,ATM_OAM_NOHEC);
526            return l2info.header_len;
527        }
528
529        if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
530            EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
531
532            if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
533                          &extracted_ethertype) != 0)
534                return l2info.header_len;
535        }
536
537        if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
538            isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
539            /* FIXME check if frame was recognized */
540            return l2info.header_len;
541        }
542
543        if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
544            return l2info.header_len;
545
546	return l2info.header_len;
547}
548#endif
549
550/*
551 *     ATM2 PIC cookie format
552 *
553 *     +-------------------------------+---------+---+-----+-----------+
554 *     |     channel ID                |  reserv |AAL| CCRQ| gap cnt   |
555 *     +-------------------------------+---------+---+-----+-----------+
556 */
557
558#ifdef DLT_JUNIPER_ATM2
559u_int
560juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p)
561{
562        u_int16_t extracted_ethertype;
563        u_int32_t control_word;
564
565        struct juniper_l2info_t l2info;
566
567        l2info.pictype = DLT_JUNIPER_ATM2;
568        if(juniper_parse_header(p, h, &l2info) == 0)
569            return l2info.header_len;
570
571        p+=l2info.header_len;
572
573        if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
574            control_word = EXTRACT_32BITS(p);
575            if(control_word == 0 || control_word == 0x08000000) {
576                l2info.header_len += 4;
577                l2info.length -= 4;
578                p += 4;
579            }
580            oam_print(p,l2info.length,ATM_OAM_NOHEC);
581            return l2info.header_len;
582        }
583
584        if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
585            EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
586
587            if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
588                          &extracted_ethertype) != 0)
589                return l2info.header_len;
590        }
591
592        if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
593            (EXTRACT_32BITS(l2info.cookie) & ATM2_GAP_COUNT_MASK)) {
594            ether_print(p, l2info.length, l2info.caplen);
595            return l2info.header_len;
596        }
597
598        if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
599            isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
600            /* FIXME check if frame was recognized */
601            return l2info.header_len;
602        }
603
604        if(juniper_ppp_heuristic_guess(p, l2info.length) != 0) /* PPPoA vcmux encaps ? */
605            return l2info.header_len;
606
607        if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
608            return l2info.header_len;
609
610	return l2info.header_len;
611}
612#endif
613
614
615/* try to guess, based on all PPP protos that are supported in
616 * a juniper router if the payload data is encapsulated using PPP */
617int
618juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
619
620    switch(EXTRACT_16BITS(p)) {
621    case PPP_IP :
622    case PPP_OSI :
623    case PPP_MPLS_UCAST :
624    case PPP_MPLS_MCAST :
625    case PPP_IPCP :
626    case PPP_OSICP :
627    case PPP_MPLSCP :
628    case PPP_LCP :
629    case PPP_PAP :
630    case PPP_CHAP :
631    case PPP_ML :
632#ifdef INET6
633    case PPP_IPV6 :
634    case PPP_IPV6CP :
635#endif
636        ppp_print(p, length);
637        break;
638
639    default:
640        return 0; /* did not find a ppp header */
641        break;
642    }
643    return 1; /* we printed a ppp packet */
644}
645
646int
647ip_heuristic_guess(register const u_char *p, u_int length) {
648
649    switch(p[0]) {
650    case 0x45:
651    case 0x46:
652    case 0x47:
653    case 0x48:
654    case 0x49:
655    case 0x4a:
656    case 0x4b:
657    case 0x4c:
658    case 0x4d:
659    case 0x4e:
660    case 0x4f:
661	    ip_print(gndo, p, length);
662	    break;
663#ifdef INET6
664    case 0x60:
665    case 0x61:
666    case 0x62:
667    case 0x63:
668    case 0x64:
669    case 0x65:
670    case 0x66:
671    case 0x67:
672    case 0x68:
673    case 0x69:
674    case 0x6a:
675    case 0x6b:
676    case 0x6c:
677    case 0x6d:
678    case 0x6e:
679    case 0x6f:
680        ip6_print(p, length);
681        break;
682#endif
683    default:
684        return 0; /* did not find a ip header */
685        break;
686    }
687    return 1; /* we printed an v4/v6 packet */
688}
689
690static int
691juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) {
692
693    struct juniper_cookie_table_t *lp = juniper_cookie_table;
694    u_int idx;
695
696    l2info->header_len = 0;
697    l2info->cookie_len = 0;
698    l2info->proto = 0;
699
700
701    l2info->length = h->len;
702    l2info->caplen = h->caplen;
703    l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
704
705    TCHECK2(p[0],4);
706    if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) /* magic number found ? */
707        return 0;
708    else
709        l2info->header_len = 4;
710
711    if (eflag) /* print direction */
712        printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction));
713
714    if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
715        if (eflag)
716            printf("no-L2-hdr, ");
717
718        /* there is no link-layer present -
719         * perform the v4/v6 heuristics
720         * to figure out what it is
721         */
722        TCHECK2(p[8],1);
723        if(ip_heuristic_guess(p+8,l2info->length-8) == 0)
724            printf("no IP-hdr found!");
725
726        l2info->header_len+=4;
727        return 0; /* stop parsing the output further */
728
729    }
730
731    p+=l2info->header_len;
732    l2info->length -= l2info->header_len;
733    l2info->caplen -= l2info->header_len;
734
735    /* search through the cookie table and copy values matching for our PIC type */
736    while (lp->s != NULL) {
737        if (lp->pictype == l2info->pictype) {
738
739            l2info->cookie_len = lp->cookie_len;
740            l2info->header_len += lp->cookie_len;
741
742            switch (p[0]) {
743            case LS_COOKIE_ID:
744                l2info->cookie_type = LS_COOKIE_ID;
745                l2info->cookie_len += 2;
746                l2info->header_len += 2;
747                break;
748            case AS_COOKIE_ID:
749                l2info->cookie_type = AS_COOKIE_ID;
750                l2info->cookie_len += 6;
751                l2info->header_len += 6;
752                break;
753
754            default:
755                l2info->bundle = l2info->cookie[0];
756                break;
757            }
758
759            if (eflag)
760                printf("%s-PIC, cookie-len %u",
761                       lp->s,
762                       l2info->cookie_len);
763
764            if (l2info->cookie_len > 0) {
765                TCHECK2(p[0],l2info->cookie_len);
766                if (eflag)
767                    printf(", cookie 0x");
768                for (idx = 0; idx < l2info->cookie_len; idx++) {
769                    l2info->cookie[idx] = p[idx]; /* copy cookie data */
770                    if (eflag) printf("%02x",p[idx]);
771                }
772            }
773
774            if (eflag) printf(": "); /* print demarc b/w L2/L3*/
775
776
777            l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len);
778            break;
779        }
780        ++lp;
781    }
782    p+=l2info->cookie_len;
783
784    /* DLT_ specific parsing */
785    switch(l2info->pictype) {
786    case DLT_JUNIPER_MLPPP:
787        switch (l2info->cookie_type) {
788        case LS_COOKIE_ID:
789            l2info->bundle = l2info->cookie[1];
790            break;
791        case AS_COOKIE_ID:
792            l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
793            l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
794            break;
795        default:
796            l2info->bundle = l2info->cookie[0];
797            break;
798        }
799        break;
800    case DLT_JUNIPER_MLFR: /* fall through */
801    case DLT_JUNIPER_MFR:
802        switch (l2info->cookie_type) {
803        case LS_COOKIE_ID:
804            l2info->bundle = l2info->cookie[1];
805            break;
806        case AS_COOKIE_ID:
807            l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
808            break;
809        default:
810            l2info->bundle = l2info->cookie[0];
811            break;
812        }
813        l2info->proto = EXTRACT_16BITS(p);
814        l2info->header_len += 2;
815        l2info->length -= 2;
816        l2info->caplen -= 2;
817        break;
818    case DLT_JUNIPER_ATM2:
819        TCHECK2(p[0],4);
820        /* ATM cell relay control word present ? */
821        if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK && *p & 0x08) {
822            l2info->header_len += 4;
823            if (eflag)
824                printf("control-word 0x%08x ",EXTRACT_32BITS(p));
825        }
826        break;
827    case DLT_JUNIPER_ATM1:
828    default:
829        break;
830    }
831
832    if (eflag > 1)
833        printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto);
834
835    return 1; /* everything went ok so far. continue parsing */
836 trunc:
837    printf("[|juniper_hdr], length %u",h->len);
838    return 0;
839}
840
841
842/*
843 * Local Variables:
844 * c-style: whitesmith
845 * c-basic-offset: 4
846 * End:
847 */
848