xref: /freebsd/contrib/tcpdump/print-juniper.c (revision 7bd6fde3)
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.19 2005/08/23 10:29:42 hannes 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         u_int32_t control_word;
674 
675         struct juniper_l2info_t l2info;
676 
677         l2info.pictype = DLT_JUNIPER_ATM2;
678         if(juniper_parse_header(p, h, &l2info) == 0)
679             return l2info.header_len;
680 
681         p+=l2info.header_len;
682 
683         if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
684             control_word = EXTRACT_32BITS(p);
685             if(control_word == 0 || control_word == 0x08000000) {
686                 l2info.header_len += 4;
687                 l2info.length -= 4;
688                 p += 4;
689             }
690             oam_print(p,l2info.length,ATM_OAM_NOHEC);
691             return l2info.header_len;
692         }
693 
694         if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
695             EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
696 
697             if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
698                           &extracted_ethertype) != 0)
699                 return l2info.header_len;
700         }
701 
702         if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
703             (EXTRACT_32BITS(l2info.cookie) & ATM2_GAP_COUNT_MASK)) {
704             ether_print(p, l2info.length, l2info.caplen);
705             return l2info.header_len;
706         }
707 
708         if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
709             isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
710             /* FIXME check if frame was recognized */
711             return l2info.header_len;
712         }
713 
714         if(juniper_ppp_heuristic_guess(p, l2info.length) != 0) /* PPPoA vcmux encaps ? */
715             return l2info.header_len;
716 
717         if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
718             return l2info.header_len;
719 
720 	return l2info.header_len;
721 }
722 #endif
723 
724 
725 /* try to guess, based on all PPP protos that are supported in
726  * a juniper router if the payload data is encapsulated using PPP */
727 int
728 juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
729 
730     switch(EXTRACT_16BITS(p)) {
731     case PPP_IP :
732     case PPP_OSI :
733     case PPP_MPLS_UCAST :
734     case PPP_MPLS_MCAST :
735     case PPP_IPCP :
736     case PPP_OSICP :
737     case PPP_MPLSCP :
738     case PPP_LCP :
739     case PPP_PAP :
740     case PPP_CHAP :
741     case PPP_ML :
742 #ifdef INET6
743     case PPP_IPV6 :
744     case PPP_IPV6CP :
745 #endif
746         ppp_print(p, length);
747         break;
748 
749     default:
750         return 0; /* did not find a ppp header */
751         break;
752     }
753     return 1; /* we printed a ppp packet */
754 }
755 
756 int
757 ip_heuristic_guess(register const u_char *p, u_int length) {
758 
759     switch(p[0]) {
760     case 0x45:
761     case 0x46:
762     case 0x47:
763     case 0x48:
764     case 0x49:
765     case 0x4a:
766     case 0x4b:
767     case 0x4c:
768     case 0x4d:
769     case 0x4e:
770     case 0x4f:
771 	    ip_print(gndo, p, length);
772 	    break;
773 #ifdef INET6
774     case 0x60:
775     case 0x61:
776     case 0x62:
777     case 0x63:
778     case 0x64:
779     case 0x65:
780     case 0x66:
781     case 0x67:
782     case 0x68:
783     case 0x69:
784     case 0x6a:
785     case 0x6b:
786     case 0x6c:
787     case 0x6d:
788     case 0x6e:
789     case 0x6f:
790         ip6_print(p, length);
791         break;
792 #endif
793     default:
794         return 0; /* did not find a ip header */
795         break;
796     }
797     return 1; /* we printed an v4/v6 packet */
798 }
799 
800 static int
801 juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) {
802 
803     struct juniper_cookie_table_t *lp = juniper_cookie_table;
804     u_int idx, offset;
805 
806     l2info->header_len = 0;
807     l2info->cookie_len = 0;
808     l2info->proto = 0;
809 
810 
811     l2info->length = h->len;
812     l2info->caplen = h->caplen;
813     l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
814 
815     TCHECK2(p[0],4);
816     if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) { /* magic number found ? */
817         printf("no magic-number found!");
818         return 0;
819     }
820 
821     if (eflag) /* print direction */
822         printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction));
823 
824     /* extensions present ?  - calculate how much bytes to skip */
825     if ((p[3] & JUNIPER_BPF_EXT ) == JUNIPER_BPF_EXT ) {
826         offset = 6 + EXTRACT_16BITS(p+4);
827         if (eflag>1)
828             printf("ext-len %u, ",EXTRACT_16BITS(p+4));
829     } else
830         offset = 4;
831 
832     if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
833         if (eflag)
834             printf("no-L2-hdr, ");
835 
836         /* there is no link-layer present -
837          * perform the v4/v6 heuristics
838          * to figure out what it is
839          */
840         TCHECK2(p[offset+4],1);
841         if(ip_heuristic_guess(p+offset+4,l2info->length-(offset+4)) == 0)
842             printf("no IP-hdr found!");
843 
844         l2info->header_len=offset+4;
845         return 0; /* stop parsing the output further */
846 
847     }
848     l2info->header_len = offset;
849     p+=l2info->header_len;
850     l2info->length -= l2info->header_len;
851     l2info->caplen -= l2info->header_len;
852 
853     /* search through the cookie table and copy values matching for our PIC type */
854     while (lp->s != NULL) {
855         if (lp->pictype == l2info->pictype) {
856 
857             l2info->cookie_len += lp->cookie_len;
858 
859             switch (p[0]) {
860             case LS_COOKIE_ID:
861                 l2info->cookie_type = LS_COOKIE_ID;
862                 l2info->cookie_len += 2;
863                 break;
864             case AS_COOKIE_ID:
865                 l2info->cookie_type = AS_COOKIE_ID;
866                 l2info->cookie_len = 8;
867                 break;
868 
869             default:
870                 l2info->bundle = l2info->cookie[0];
871                 break;
872             }
873 
874 
875 #ifdef DLT_JUNIPER_MFR
876             /* MFR child links don't carry cookies */
877             if (l2info->pictype == DLT_JUNIPER_MFR &&
878                 (p[0] & MFR_BE_MASK) == MFR_BE_MASK) {
879                 l2info->cookie_len = 0;
880             }
881 #endif
882 
883             l2info->header_len += l2info->cookie_len;
884             l2info->length -= l2info->cookie_len;
885             l2info->caplen -= l2info->cookie_len;
886 
887             if (eflag)
888                 printf("%s-PIC, cookie-len %u",
889                        lp->s,
890                        l2info->cookie_len);
891 
892             if (l2info->cookie_len > 0) {
893                 TCHECK2(p[0],l2info->cookie_len);
894                 if (eflag)
895                     printf(", cookie 0x");
896                 for (idx = 0; idx < l2info->cookie_len; idx++) {
897                     l2info->cookie[idx] = p[idx]; /* copy cookie data */
898                     if (eflag) printf("%02x",p[idx]);
899                 }
900             }
901 
902             if (eflag) printf(": "); /* print demarc b/w L2/L3*/
903 
904 
905             l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len);
906             break;
907         }
908         ++lp;
909     }
910     p+=l2info->cookie_len;
911 
912     /* DLT_ specific parsing */
913     switch(l2info->pictype) {
914 #ifdef DLT_JUNIPER_MLPPP
915     case DLT_JUNIPER_MLPPP:
916         switch (l2info->cookie_type) {
917         case LS_COOKIE_ID:
918             l2info->bundle = l2info->cookie[1];
919             break;
920         case AS_COOKIE_ID:
921             l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
922             l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
923             break;
924         default:
925             l2info->bundle = l2info->cookie[0];
926             break;
927         }
928         break;
929 #endif
930 #ifdef DLT_JUNIPER_MLFR
931     case DLT_JUNIPER_MLFR:
932         switch (l2info->cookie_type) {
933         case LS_COOKIE_ID:
934             l2info->bundle = l2info->cookie[1];
935             l2info->proto = EXTRACT_16BITS(p);
936             l2info->header_len += 2;
937             l2info->length -= 2;
938             l2info->caplen -= 2;
939             break;
940         case AS_COOKIE_ID:
941             l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
942             l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
943             break;
944         default:
945             l2info->bundle = l2info->cookie[0];
946             l2info->header_len += 2;
947             l2info->length -= 2;
948             l2info->caplen -= 2;
949             break;
950         }
951         break;
952 #endif
953 #ifdef DLT_JUNIPER_MFR
954     case DLT_JUNIPER_MFR:
955         switch (l2info->cookie_type) {
956         case LS_COOKIE_ID:
957             l2info->bundle = l2info->cookie[1];
958             l2info->proto = EXTRACT_16BITS(p);
959             l2info->header_len += 2;
960             l2info->length -= 2;
961             l2info->caplen -= 2;
962             break;
963         case AS_COOKIE_ID:
964             l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
965             l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
966             break;
967         default:
968             l2info->bundle = l2info->cookie[0];
969             break;
970         }
971         break;
972 #endif
973 #ifdef DLT_JUNIPER_ATM2
974     case DLT_JUNIPER_ATM2:
975         TCHECK2(p[0],4);
976         /* ATM cell relay control word present ? */
977         if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK && *p & 0x08) {
978             l2info->header_len += 4;
979             if (eflag)
980                 printf("control-word 0x%08x ",EXTRACT_32BITS(p));
981         }
982         break;
983 #endif
984 #ifdef DLT_JUNIPER_ATM1
985     case DLT_JUNIPER_ATM1:
986         break;
987 #endif
988     default:
989         printf("Unknown Juniper DLT_ type %u: ", l2info->pictype);
990         break;
991     }
992 
993     if (eflag > 1)
994         printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto);
995 
996     return 1; /* everything went ok so far. continue parsing */
997  trunc:
998     printf("[|juniper_hdr], length %u",h->len);
999     return 0;
1000 }
1001 
1002 
1003 /*
1004  * Local Variables:
1005  * c-style: whitesmith
1006  * c-basic-offset: 4
1007  * End:
1008  */
1009