]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/tcpdump/print-juniper.c
This commit was generated by cvs2svn to compensate for changes in r157043,
[FreeBSD/FreeBSD.git] / contrib / tcpdump / print-juniper.c
1 /* 
2  * Redistribution and use in source and binary forms, with or without
3  * modification, are permitted provided that: (1) source code
4  * distributions retain the above copyright notice and this paragraph
5  * in its entirety, and (2) distributions including binary code include
6  * the above copyright notice and this paragraph in its entirety in
7  * the documentation or other materials provided with the distribution.
8  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND
9  * WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT
10  * LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
11  * FOR A PARTICULAR PURPOSE.
12  *
13  * Original code by Hannes Gredler (hannes@juniper.net)
14  */
15
16 #ifndef lint
17 static const char rcsid[] _U_ =
18     "@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.8.2.13 2005/06/20 07:45:05 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_MGC_NUMBER        0x4d4743 /* = "MGC" */
44
45 #define JUNIPER_LSQ_L3_PROTO_SHIFT     4
46 #define JUNIPER_LSQ_L3_PROTO_MASK     (0x17 << JUNIPER_LSQ_L3_PROTO_SHIFT)
47 #define JUNIPER_LSQ_L3_PROTO_IPV4     (0 << JUNIPER_LSQ_L3_PROTO_SHIFT)
48 #define JUNIPER_LSQ_L3_PROTO_IPV6     (1 << JUNIPER_LSQ_L3_PROTO_SHIFT)
49 #define JUNIPER_LSQ_L3_PROTO_MPLS     (2 << JUNIPER_LSQ_L3_PROTO_SHIFT)
50 #define JUNIPER_LSQ_L3_PROTO_ISO      (3 << JUNIPER_LSQ_L3_PROTO_SHIFT)
51
52 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE 1
53 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE 2
54 #define JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE 3
55 #define JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE 4
56 #define JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE 5
57
58 static struct tok juniper_ipsec_type_values[] = {
59     { JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE, "ESP ENCR-AUTH" },
60     { JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE, "ESP ENCR-AH AUTH" },
61     { JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE, "ESP AUTH" },
62     { JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE, "AH AUTH" },
63     { JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE, "ESP ENCR" },
64     { 0, NULL}
65 };
66
67 static struct tok juniper_direction_values[] = {
68     { JUNIPER_BPF_IN,  "In"},
69     { JUNIPER_BPF_OUT, "Out"},
70     { 0, NULL}
71 };
72
73 struct juniper_cookie_table_t {
74     u_int32_t pictype;          /* pic type */
75     u_int8_t  cookie_len;       /* cookie len */
76     const char *s;              /* pic name */
77 };
78
79 static struct juniper_cookie_table_t juniper_cookie_table[] = {
80 #ifdef DLT_JUNIPER_ATM1
81     { DLT_JUNIPER_ATM1,  4, "ATM1"},
82 #endif
83 #ifdef DLT_JUNIPER_ATM2
84     { DLT_JUNIPER_ATM2,  8, "ATM2"},
85 #endif
86 #ifdef DLT_JUNIPER_MLPPP
87     { DLT_JUNIPER_MLPPP, 2, "MLPPP"},
88 #endif
89 #ifdef DLT_JUNIPER_MLFR
90     { DLT_JUNIPER_MLFR,  2, "MLFR"},
91 #endif
92 #ifdef DLT_JUNIPER_MFR
93     { DLT_JUNIPER_MFR,   4, "MFR"},
94 #endif
95 #ifdef DLT_JUNIPER_PPPOE
96     { DLT_JUNIPER_PPPOE, 0, "PPPoE"},
97 #endif
98 #ifdef DLT_JUNIPER_PPPOE_ATM
99     { DLT_JUNIPER_PPPOE_ATM, 0, "PPPoE ATM"},
100 #endif
101 #ifdef DLT_JUNIPER_GGSN
102     { DLT_JUNIPER_GGSN, 8, "GGSN"},
103 #endif
104 #ifdef DLT_JUNIPER_MONITOR
105     { DLT_JUNIPER_MONITOR, 8, "MONITOR"},
106 #endif
107 #ifdef DLT_JUNIPER_SERVICES
108     { DLT_JUNIPER_SERVICES, 8, "AS"},
109 #endif
110 #ifdef DLT_JUNIPER_ES
111     { DLT_JUNIPER_ES, 0, "ES"},
112 #endif
113     { 0, 0, NULL }
114 };
115
116 struct juniper_l2info_t {
117     u_int32_t length;
118     u_int32_t caplen;
119     u_int32_t pictype;
120     u_int8_t direction;
121     u_int8_t header_len;
122     u_int8_t cookie_len;
123     u_int8_t cookie_type;
124     u_int8_t cookie[8];
125     u_int8_t bundle;
126     u_int16_t proto;
127 };
128
129 #define LS_COOKIE_ID            0x54
130 #define AS_COOKIE_ID            0x47
131 #define LS_MLFR_COOKIE_LEN      4
132 #define ML_MLFR_COOKIE_LEN      2
133 #define LS_MFR_COOKIE_LEN       6
134 #define ATM1_COOKIE_LEN         4
135 #define ATM2_COOKIE_LEN         8
136
137 #define ATM2_PKT_TYPE_MASK  0x70
138 #define ATM2_GAP_COUNT_MASK 0x3F
139
140 #define JUNIPER_PROTO_NULL          1
141 #define JUNIPER_PROTO_IPV4          2
142 #define JUNIPER_PROTO_IPV6          6
143
144 static struct tok juniper_protocol_values[] = {
145     { JUNIPER_PROTO_NULL, "Null" },
146     { JUNIPER_PROTO_IPV4, "IPv4" },
147     { JUNIPER_PROTO_IPV6, "IPv6" },
148     { 0, NULL}
149 };
150
151 int ip_heuristic_guess(register const u_char *, u_int);
152 int juniper_ppp_heuristic_guess(register const u_char *, u_int);
153 static int juniper_parse_header (const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
154
155 #ifdef DLT_JUNIPER_GGSN
156 u_int
157 juniper_ggsn_print(const struct pcap_pkthdr *h, register const u_char *p)
158 {
159         struct juniper_l2info_t l2info;
160         struct juniper_ggsn_header {
161             u_int8_t svc_id;
162             u_int8_t flags_len;
163             u_int8_t proto;
164             u_int8_t flags;
165             u_int8_t vlan_id[2];
166             u_int8_t res[2];
167         };
168         const struct juniper_ggsn_header *gh;
169
170         l2info.pictype = DLT_JUNIPER_GGSN;
171         if(juniper_parse_header(p, h, &l2info) == 0)
172             return l2info.header_len;
173
174         p+=l2info.header_len;
175         gh = (struct juniper_ggsn_header *)p;
176
177         if (eflag)
178             printf("proto %s (%u), vlan %u: ",
179                    tok2str(juniper_protocol_values,"Unknown",gh->proto),
180                    gh->proto,
181                    EXTRACT_16BITS(&gh->vlan_id[0]));
182
183         switch (gh->proto) {
184         case JUNIPER_PROTO_IPV4:
185             ip_print(gndo, p, l2info.length);
186             break;
187 #ifdef INET6
188         case JUNIPER_PROTO_IPV6:
189             ip6_print(p, l2info.length);
190             break;
191 #endif /* INET6 */
192         default:
193             if (!eflag)
194                 printf("unknown GGSN proto (%u)", gh->proto);
195         }
196
197         return l2info.header_len;
198 }
199 #endif
200
201 #ifdef DLT_JUNIPER_ES
202 u_int
203 juniper_es_print(const struct pcap_pkthdr *h, register const u_char *p)
204 {
205         struct juniper_l2info_t l2info;
206         struct juniper_ipsec_header {
207             u_int8_t sa_index[2];
208             u_int8_t ttl;
209             u_int8_t type;
210             u_int8_t spi[4];
211             u_int8_t src_ip[4];
212             u_int8_t dst_ip[4];
213         };
214         u_int rewrite_len,es_type_bundle;
215         const struct juniper_ipsec_header *ih;
216
217         l2info.pictype = DLT_JUNIPER_ES;
218         if(juniper_parse_header(p, h, &l2info) == 0)
219             return l2info.header_len;
220
221         p+=l2info.header_len;
222         ih = (struct juniper_ipsec_header *)p;
223
224         switch (ih->type) {
225         case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE:
226         case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE:
227             rewrite_len = 0;
228             es_type_bundle = 1;
229             break;
230         case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE:
231         case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE:
232         case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE:
233             rewrite_len = 16;
234             es_type_bundle = 0;
235         default:
236             printf("ES Invalid type %u, length %u",
237                    ih->type,
238                    l2info.length);
239             return l2info.header_len;
240         }
241
242         l2info.length-=rewrite_len;
243         p+=rewrite_len;
244
245         if (eflag) {
246             if (!es_type_bundle) {
247                 printf("ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n", 
248                        EXTRACT_16BITS(&ih->sa_index),
249                        ih->ttl, 
250                        tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
251                        ih->type,
252                        EXTRACT_32BITS(&ih->spi),
253                        ipaddr_string(EXTRACT_32BITS(&ih->src_ip)),
254                        ipaddr_string(EXTRACT_32BITS(&ih->dst_ip)),
255                        l2info.length);
256             } else {
257                 printf("ES SA, index %u, ttl %u type %s (%u), length %u\n", 
258                        EXTRACT_16BITS(&ih->sa_index),
259                        ih->ttl, 
260                        tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
261                        ih->type,
262                        l2info.length);
263             }
264         }
265
266         ip_print(gndo, p, l2info.length);
267         return l2info.header_len;
268 }
269 #endif
270
271 #ifdef DLT_JUNIPER_MONITOR
272 u_int
273 juniper_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
305 u_int
306 juniper_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
339 u_int
340 juniper_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
356 u_int
357 juniper_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
384 u_int
385 juniper_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
439 u_int
440 juniper_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
470 u_int
471 juniper_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
511 u_int
512 juniper_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
559 u_int
560 juniper_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 */
617 int
618 juniper_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
646 int
647 ip_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
690 static int
691 juniper_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  */