]> The Tcpdump Group git mirrors - tcpdump/blob - print-juniper.c
Protect code for particular Juniper DLT_ values with #ifdefs, so this
[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.18 2005-06-03 22:03:02 guy Exp $ (LBL)";
19 #endif
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <tcpdump-stdinc.h>
26
27 #include <pcap.h>
28 #include <stdio.h>
29
30 #include "interface.h"
31 #include "addrtoname.h"
32 #include "extract.h"
33 #include "ppp.h"
34 #include "llc.h"
35 #include "nlpid.h"
36 #include "ethertype.h"
37
38 #define JUNIPER_BPF_OUT 0 /* Outgoing packet */
39 #define JUNIPER_BPF_IN 1 /* Incoming packet */
40 #define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */
41 #define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */
42 #define JUNIPER_MGC_NUMBER 0x4d4743 /* = "MGC" */
43
44 #define JUNIPER_LSQ_L3_PROTO_SHIFT 4
45 #define JUNIPER_LSQ_L3_PROTO_MASK (0x17 << JUNIPER_LSQ_L3_PROTO_SHIFT)
46 #define JUNIPER_LSQ_L3_PROTO_IPV4 (0 << JUNIPER_LSQ_L3_PROTO_SHIFT)
47 #define JUNIPER_LSQ_L3_PROTO_IPV6 (1 << JUNIPER_LSQ_L3_PROTO_SHIFT)
48 #define JUNIPER_LSQ_L3_PROTO_MPLS (2 << JUNIPER_LSQ_L3_PROTO_SHIFT)
49 #define JUNIPER_LSQ_L3_PROTO_ISO (3 << JUNIPER_LSQ_L3_PROTO_SHIFT)
50
51 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE 1
52 #define JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE 2
53 #define JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE 3
54 #define JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE 4
55 #define JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE 5
56
57 static struct tok juniper_ipsec_type_values[] = {
58 { JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE, "ESP ENCR-AUTH" },
59 { JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE, "ESP ENCR-AH AUTH" },
60 { JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE, "ESP AUTH" },
61 { JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE, "AH AUTH" },
62 { JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE, "ESP ENCR" },
63 { 0, NULL}
64 };
65
66 static struct tok juniper_direction_values[] = {
67 { JUNIPER_BPF_IN, "In"},
68 { JUNIPER_BPF_OUT, "Out"},
69 { 0, NULL}
70 };
71
72 struct juniper_cookie_table_t {
73 u_int32_t pictype; /* pic type */
74 u_int8_t cookie_len; /* cookie len */
75 const char *s; /* pic name */
76 };
77
78 static struct juniper_cookie_table_t juniper_cookie_table[] = {
79 #ifdef DLT_JUNIPER_ATM1
80 { DLT_JUNIPER_ATM1, 4, "ATM1"},
81 #endif
82 #ifdef DLT_JUNIPER_ATM2
83 { DLT_JUNIPER_ATM2, 8, "ATM2"},
84 #endif
85 #ifdef DLT_JUNIPER_MLPPP
86 { DLT_JUNIPER_MLPPP, 2, "MLPPP"},
87 #endif
88 #ifdef DLT_JUNIPER_MLFR
89 { DLT_JUNIPER_MLFR, 2, "MLFR"},
90 #endif
91 #ifdef DLT_JUNIPER_MFR
92 { DLT_JUNIPER_MFR, 4, "MFR"},
93 #endif
94 #ifdef DLT_JUNIPER_PPPOE
95 { DLT_JUNIPER_PPPOE, 0, "PPPoE"},
96 #endif
97 #ifdef DLT_JUNIPER_PPPOE_ATM
98 { DLT_JUNIPER_PPPOE_ATM, 0, "PPPoE ATM"},
99 #endif
100 #ifdef DLT_JUNIPER_GGSN
101 { DLT_JUNIPER_GGSN, 8, "GGSN"},
102 #endif
103 #ifdef DLT_JUNIPER_MONITOR
104 { DLT_JUNIPER_MONITOR, 8, "MONITOR"},
105 #endif
106 #ifdef DLT_JUNIPER_SERVICES
107 { DLT_JUNIPER_SERVICES, 8, "AS"},
108 #endif
109 #ifdef DLT_JUNIPER_ES
110 { DLT_JUNIPER_ES, 0, "ES"},
111 #endif
112 { 0, 0, NULL }
113 };
114
115 struct juniper_l2info_t {
116 u_int32_t length;
117 u_int32_t caplen;
118 u_int32_t pictype;
119 u_int8_t direction;
120 u_int8_t header_len;
121 u_int8_t cookie_len;
122 u_int8_t cookie_type;
123 u_int8_t cookie[8];
124 u_int8_t bundle;
125 u_int16_t proto;
126 };
127
128 #define LS_COOKIE_ID 0x54
129 #define AS_COOKIE_ID 0x47
130 #define LS_MLFR_COOKIE_LEN 4
131 #define ML_MLFR_COOKIE_LEN 2
132 #define LS_MFR_COOKIE_LEN 6
133 #define ATM1_COOKIE_LEN 4
134 #define ATM2_COOKIE_LEN 8
135
136 #define ATM2_PKT_TYPE_MASK 0x70
137 #define ATM2_GAP_COUNT_MASK 0x3F
138
139 #define JUNIPER_PROTO_NULL 1
140 #define JUNIPER_PROTO_IPV4 2
141 #define JUNIPER_PROTO_IPV6 6
142
143 static struct tok juniper_protocol_values[] = {
144 { JUNIPER_PROTO_NULL, "Null" },
145 { JUNIPER_PROTO_IPV4, "IPv4" },
146 { JUNIPER_PROTO_IPV6, "IPv6" },
147 { 0, NULL}
148 };
149
150 int ip_heuristic_guess(register const u_char *, u_int);
151 int juniper_ppp_heuristic_guess(register const u_char *, u_int);
152 static int juniper_parse_header (const u_char *, const struct pcap_pkthdr *, struct juniper_l2info_t *);
153
154 #ifdef DLT_JUNIPER_GGSN
155 u_int
156 juniper_ggsn_print(const struct pcap_pkthdr *h, register const u_char *p)
157 {
158 struct juniper_l2info_t l2info;
159 struct juniper_ggsn_header {
160 u_int8_t svc_id;
161 u_int8_t flags_len;
162 u_int8_t proto;
163 u_int8_t flags;
164 u_int8_t vlan_id[2];
165 u_int8_t res[2];
166 };
167 const struct juniper_ggsn_header *gh;
168
169 l2info.pictype = DLT_JUNIPER_GGSN;
170 if(juniper_parse_header(p, h, &l2info) == 0)
171 return l2info.header_len;
172
173 p+=l2info.header_len;
174 gh = (struct juniper_ggsn_header *)p;
175
176 if (eflag)
177 printf("proto %s (%u), vlan %u: ",
178 tok2str(juniper_protocol_values,"Unknown",gh->proto),
179 gh->proto,
180 EXTRACT_16BITS(&gh->vlan_id[0]));
181
182 switch (gh->proto) {
183 case JUNIPER_PROTO_IPV4:
184 ip_print(gndo, p, l2info.length);
185 break;
186 #ifdef INET6
187 case JUNIPER_PROTO_IPV6:
188 ip6_print(p, l2info.length);
189 break;
190 #endif /* INET6 */
191 default:
192 if (!eflag)
193 printf("unknown GGSN proto (%u)", gh->proto);
194 }
195
196 return l2info.header_len;
197 }
198 #endif
199
200 #ifdef DLT_JUNIPER_ES
201 u_int
202 juniper_es_print(const struct pcap_pkthdr *h, register const u_char *p)
203 {
204 struct juniper_l2info_t l2info;
205 struct juniper_ipsec_header {
206 u_int8_t sa_index[2];
207 u_int8_t ttl;
208 u_int8_t type;
209 u_int8_t spi[4];
210 u_int8_t src_ip[4];
211 u_int8_t dst_ip[4];
212 };
213 u_int rewrite_len,es_type_bundle;
214 const struct juniper_ipsec_header *ih;
215
216 l2info.pictype = DLT_JUNIPER_ES;
217 if(juniper_parse_header(p, h, &l2info) == 0)
218 return l2info.header_len;
219
220 p+=l2info.header_len;
221 ih = (struct juniper_ipsec_header *)p;
222
223 switch (ih->type) {
224 case JUNIPER_IPSEC_O_ESP_ENCRYPT_ESP_AUTHEN_TYPE:
225 case JUNIPER_IPSEC_O_ESP_ENCRYPT_AH_AUTHEN_TYPE:
226 rewrite_len = 0;
227 es_type_bundle = 1;
228 break;
229 case JUNIPER_IPSEC_O_ESP_AUTHENTICATION_TYPE:
230 case JUNIPER_IPSEC_O_AH_AUTHENTICATION_TYPE:
231 case JUNIPER_IPSEC_O_ESP_ENCRYPTION_TYPE:
232 rewrite_len = 16;
233 es_type_bundle = 0;
234 default:
235 printf("ES Invalid type %u, length %u",
236 ih->type,
237 l2info.length);
238 return l2info.header_len;
239 }
240
241 l2info.length-=rewrite_len;
242 p+=rewrite_len;
243
244 if (eflag) {
245 if (!es_type_bundle) {
246 printf("ES SA, index %u, ttl %u type %s (%u), spi %u, Tunnel %s > %s, length %u\n",
247 EXTRACT_16BITS(&ih->sa_index),
248 ih->ttl,
249 tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
250 ih->type,
251 EXTRACT_32BITS(&ih->spi),
252 ipaddr_string(EXTRACT_32BITS(&ih->src_ip)),
253 ipaddr_string(EXTRACT_32BITS(&ih->dst_ip)),
254 l2info.length);
255 } else {
256 printf("ES SA, index %u, ttl %u type %s (%u), length %u\n",
257 EXTRACT_16BITS(&ih->sa_index),
258 ih->ttl,
259 tok2str(juniper_ipsec_type_values,"Unknown",ih->type),
260 ih->type,
261 l2info.length);
262 }
263 }
264
265 ip_print(gndo, p, l2info.length);
266 return l2info.header_len;
267 }
268 #endif
269
270 #ifdef DLT_JUNIPER_MONITOR
271 u_int
272 juniper_monitor_print(const struct pcap_pkthdr *h, register const u_char *p)
273 {
274 struct juniper_l2info_t l2info;
275 struct juniper_monitor_header {
276 u_int8_t pkt_type;
277 u_int8_t padding;
278 u_int8_t iif[2];
279 u_int8_t service_id[4];
280 };
281 const struct juniper_monitor_header *mh;
282
283 l2info.pictype = DLT_JUNIPER_MONITOR;
284 if(juniper_parse_header(p, h, &l2info) == 0)
285 return l2info.header_len;
286
287 p+=l2info.header_len;
288 mh = (struct juniper_monitor_header *)p;
289
290 if (eflag)
291 printf("service-id %u, iif %u, pkt-type %u: ",
292 EXTRACT_32BITS(&mh->service_id),
293 EXTRACT_16BITS(&mh->iif),
294 mh->pkt_type);
295
296 /* no proto field - lets guess by first byte of IP header*/
297 ip_heuristic_guess(p, l2info.length);
298
299 return l2info.header_len;
300 }
301 #endif
302
303 #ifdef DLT_JUNIPER_SERVICES
304 u_int
305 juniper_services_print(const struct pcap_pkthdr *h, register const u_char *p)
306 {
307 struct juniper_l2info_t l2info;
308 struct juniper_services_header {
309 u_int8_t svc_id;
310 u_int8_t flags_len;
311 u_int8_t svc_set_id[2];
312 u_int8_t dir_iif[4];
313 };
314 const struct juniper_services_header *sh;
315
316 l2info.pictype = DLT_JUNIPER_SERVICES;
317 if(juniper_parse_header(p, h, &l2info) == 0)
318 return l2info.header_len;
319
320 p+=l2info.header_len;
321 sh = (struct juniper_services_header *)p;
322
323 if (eflag)
324 printf("service-id %u flags 0x%02x service-set-id 0x%04x iif %u: ",
325 sh->svc_id,
326 sh->flags_len,
327 EXTRACT_16BITS(&sh->svc_set_id),
328 EXTRACT_24BITS(&sh->dir_iif[1]));
329
330 /* no proto field - lets guess by first byte of IP header*/
331 ip_heuristic_guess(p, l2info.length);
332
333 return l2info.header_len;
334 }
335 #endif
336
337 #ifdef DLT_JUNIPER_PPPOE
338 u_int
339 juniper_pppoe_print(const struct pcap_pkthdr *h, register const u_char *p)
340 {
341 struct juniper_l2info_t l2info;
342
343 l2info.pictype = DLT_JUNIPER_PPPOE;
344 if(juniper_parse_header(p, h, &l2info) == 0)
345 return l2info.header_len;
346
347 p+=l2info.header_len;
348 /* this DLT contains nothing but raw ethernet frames */
349 ether_print(p, l2info.length, l2info.caplen);
350 return l2info.header_len;
351 }
352 #endif
353
354 #ifdef DLT_JUNIPER_PPPOE_ATM
355 u_int
356 juniper_pppoe_atm_print(const struct pcap_pkthdr *h, register const u_char *p)
357 {
358 struct juniper_l2info_t l2info;
359 u_int16_t extracted_ethertype;
360
361 l2info.pictype = DLT_JUNIPER_PPPOE_ATM;
362 if(juniper_parse_header(p, h, &l2info) == 0)
363 return l2info.header_len;
364
365 p+=l2info.header_len;
366
367 extracted_ethertype = EXTRACT_16BITS(p);
368 /* this DLT contains nothing but raw PPPoE frames,
369 * prepended with a type field*/
370 if (ether_encap_print(extracted_ethertype,
371 p+ETHERTYPE_LEN,
372 l2info.length-ETHERTYPE_LEN,
373 l2info.caplen-ETHERTYPE_LEN,
374 &extracted_ethertype) == 0)
375 /* ether_type not known, probably it wasn't one */
376 printf("unknown ethertype 0x%04x", extracted_ethertype);
377
378 return l2info.header_len;
379 }
380 #endif
381
382 #ifdef DLT_JUNIPER_MLPPP
383 u_int
384 juniper_mlppp_print(const struct pcap_pkthdr *h, register const u_char *p)
385 {
386 struct juniper_l2info_t l2info;
387
388 l2info.pictype = DLT_JUNIPER_MLPPP;
389 if(juniper_parse_header(p, h, &l2info) == 0)
390 return l2info.header_len;
391
392 /* suppress Bundle-ID if frame was captured on a child-link
393 * best indicator if the cookie looks like a proto */
394 if (eflag &&
395 EXTRACT_16BITS(&l2info.cookie) != PPP_OSI &&
396 EXTRACT_16BITS(&l2info.cookie) != (PPP_ADDRESS << 8 | PPP_CONTROL))
397 printf("Bundle-ID %u: ",l2info.bundle);
398
399 p+=l2info.header_len;
400
401 /* first try the LSQ protos */
402 switch(l2info.proto) {
403 case JUNIPER_LSQ_L3_PROTO_IPV4:
404 ip_print(gndo, p, l2info.length);
405 return l2info.header_len;
406 case JUNIPER_LSQ_L3_PROTO_IPV6:
407 ip6_print(p,l2info.length);
408 return l2info.header_len;
409 case JUNIPER_LSQ_L3_PROTO_MPLS:
410 mpls_print(p,l2info.length);
411 return l2info.header_len;
412 case JUNIPER_LSQ_L3_PROTO_ISO:
413 isoclns_print(p,l2info.length,l2info.caplen);
414 return l2info.header_len;
415 default:
416 break;
417 }
418
419 /* zero length cookie ? */
420 switch (EXTRACT_16BITS(&l2info.cookie)) {
421 case PPP_OSI:
422 ppp_print(p-2,l2info.length+2);
423 break;
424 case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */
425 default:
426 ppp_print(p,l2info.length);
427 break;
428 }
429
430 return l2info.header_len;
431 }
432 #endif
433
434
435 #ifdef DLT_JUNIPER_MFR
436 u_int
437 juniper_mfr_print(const struct pcap_pkthdr *h, register const u_char *p)
438 {
439 struct juniper_l2info_t l2info;
440
441 l2info.pictype = DLT_JUNIPER_MFR;
442 if(juniper_parse_header(p, h, &l2info) == 0)
443 return l2info.header_len;
444
445 p+=l2info.header_len;
446 /* suppress Bundle-ID if frame was captured on a child-link */
447 if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
448 switch (l2info.proto) {
449 case (LLCSAP_ISONS<<8 | LLCSAP_ISONS):
450 isoclns_print(p+1, l2info.length-1, l2info.caplen-1);
451 break;
452 case (LLC_UI<<8 | NLPID_Q933):
453 case (LLC_UI<<8 | NLPID_IP):
454 case (LLC_UI<<8 | NLPID_IP6):
455 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
456 isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
457 break;
458 default:
459 printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
460 }
461
462 return l2info.header_len;
463 }
464 #endif
465
466 #ifdef DLT_JUNIPER_MLFR
467 u_int
468 juniper_mlfr_print(const struct pcap_pkthdr *h, register const u_char *p)
469 {
470 struct juniper_l2info_t l2info;
471
472 l2info.pictype = DLT_JUNIPER_MLFR;
473 if(juniper_parse_header(p, h, &l2info) == 0)
474 return l2info.header_len;
475
476 p+=l2info.header_len;
477
478 /* suppress Bundle-ID if frame was captured on a child-link */
479 if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
480 switch (l2info.proto) {
481 case (LLC_UI):
482 case (LLC_UI<<8):
483 isoclns_print(p, l2info.length, l2info.caplen);
484 break;
485 case (LLC_UI<<8 | NLPID_Q933):
486 case (LLC_UI<<8 | NLPID_IP):
487 case (LLC_UI<<8 | NLPID_IP6):
488 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
489 isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
490 break;
491 default:
492 printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
493 }
494
495 return l2info.header_len;
496 }
497 #endif
498
499 /*
500 * ATM1 PIC cookie format
501 *
502 * +-----+-------------------------+-------------------------------+
503 * |fmtid| vc index | channel ID |
504 * +-----+-------------------------+-------------------------------+
505 */
506
507 #ifdef DLT_JUNIPER_ATM1
508 u_int
509 juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p)
510 {
511 u_int16_t extracted_ethertype;
512
513 struct juniper_l2info_t l2info;
514
515 l2info.pictype = DLT_JUNIPER_ATM1;
516 if(juniper_parse_header(p, h, &l2info) == 0)
517 return l2info.header_len;
518
519 p+=l2info.header_len;
520
521 if (l2info.cookie[0] == 0x80) { /* OAM cell ? */
522 oam_print(p,l2info.length);
523 return l2info.header_len;
524 }
525
526 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
527 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
528
529 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
530 &extracted_ethertype) != 0)
531 return l2info.header_len;
532 }
533
534 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
535 isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
536 /* FIXME check if frame was recognized */
537 return l2info.header_len;
538 }
539
540 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
541 return l2info.header_len;
542
543 return l2info.header_len;
544 }
545 #endif
546
547 /*
548 * ATM2 PIC cookie format
549 *
550 * +-------------------------------+---------+---+-----+-----------+
551 * | channel ID | reserv |AAL| CCRQ| gap cnt |
552 * +-------------------------------+---------+---+-----+-----------+
553 */
554
555 #ifdef DLT_JUNIPER_ATM2
556 u_int
557 juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p)
558 {
559 u_int16_t extracted_ethertype;
560
561 struct juniper_l2info_t l2info;
562
563 l2info.pictype = DLT_JUNIPER_ATM2;
564 if(juniper_parse_header(p, h, &l2info) == 0)
565 return l2info.header_len;
566
567 p+=l2info.header_len;
568
569 if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
570 oam_print(p,l2info.length);
571 return l2info.header_len;
572 }
573
574 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
575 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
576
577 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
578 &extracted_ethertype) != 0)
579 return l2info.header_len;
580 }
581
582 if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
583 (EXTRACT_32BITS(l2info.cookie) & ATM2_GAP_COUNT_MASK)) {
584 ether_print(p, l2info.length, l2info.caplen);
585 return l2info.header_len;
586 }
587
588 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
589 isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
590 /* FIXME check if frame was recognized */
591 return l2info.header_len;
592 }
593
594 if(juniper_ppp_heuristic_guess(p, l2info.length) != 0) /* PPPoA vcmux encaps ? */
595 return l2info.header_len;
596
597 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
598 return l2info.header_len;
599
600 return l2info.header_len;
601 }
602 #endif
603
604
605 /* try to guess, based on all PPP protos that are supported in
606 * a juniper router if the payload data is encapsulated using PPP */
607 int
608 juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
609
610 switch(EXTRACT_16BITS(p)) {
611 case PPP_IP :
612 case PPP_OSI :
613 case PPP_MPLS_UCAST :
614 case PPP_MPLS_MCAST :
615 case PPP_IPCP :
616 case PPP_OSICP :
617 case PPP_MPLSCP :
618 case PPP_LCP :
619 case PPP_PAP :
620 case PPP_CHAP :
621 case PPP_ML :
622 #ifdef INET6
623 case PPP_IPV6 :
624 case PPP_IPV6CP :
625 #endif
626 ppp_print(p, length);
627 break;
628
629 default:
630 return 0; /* did not find a ppp header */
631 break;
632 }
633 return 1; /* we printed a ppp packet */
634 }
635
636 int
637 ip_heuristic_guess(register const u_char *p, u_int length) {
638
639 switch(p[0]) {
640 case 0x45:
641 case 0x46:
642 case 0x47:
643 case 0x48:
644 case 0x49:
645 case 0x4a:
646 case 0x4b:
647 case 0x4c:
648 case 0x4d:
649 case 0x4e:
650 case 0x4f:
651 ip_print(gndo, p, length);
652 break;
653 #ifdef INET6
654 case 0x60:
655 case 0x61:
656 case 0x62:
657 case 0x63:
658 case 0x64:
659 case 0x65:
660 case 0x66:
661 case 0x67:
662 case 0x68:
663 case 0x69:
664 case 0x6a:
665 case 0x6b:
666 case 0x6c:
667 case 0x6d:
668 case 0x6e:
669 case 0x6f:
670 ip6_print(p, length);
671 break;
672 #endif
673 default:
674 return 0; /* did not find a ip header */
675 break;
676 }
677 return 1; /* we printed an v4/v6 packet */
678 }
679
680 static int
681 juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) {
682
683 struct juniper_cookie_table_t *lp = juniper_cookie_table;
684 u_int idx;
685
686 l2info->header_len = 0;
687 l2info->cookie_len = 0;
688 l2info->proto = 0;
689
690
691 l2info->length = h->len;
692 l2info->caplen = h->caplen;
693 l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
694
695 TCHECK2(p[0],4);
696 if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) /* magic number found ? */
697 return 0;
698 else
699 l2info->header_len = 4;
700
701 if (eflag) /* print direction */
702 printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction));
703
704 if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
705 if (eflag)
706 printf("no-L2-hdr, ");
707
708 /* there is no link-layer present -
709 * perform the v4/v6 heuristics
710 * to figure out what it is
711 */
712 TCHECK2(p[8],1);
713 if(ip_heuristic_guess(p+8,l2info->length-8) == 0)
714 printf("no IP-hdr found!");
715
716 l2info->header_len+=4;
717 return 0; /* stop parsing the output further */
718
719 }
720
721 p+=l2info->header_len;
722 l2info->length -= l2info->header_len;
723 l2info->caplen -= l2info->header_len;
724
725 /* search through the cookie table and copy values matching for our PIC type */
726 while (lp->s != NULL) {
727 if (lp->pictype == l2info->pictype) {
728
729 l2info->cookie_len = lp->cookie_len;
730 l2info->header_len += lp->cookie_len;
731
732 switch (p[0]) {
733 case LS_COOKIE_ID:
734 l2info->cookie_type = LS_COOKIE_ID;
735 l2info->cookie_len += 2;
736 l2info->header_len += 2;
737 break;
738 case AS_COOKIE_ID:
739 l2info->cookie_type = AS_COOKIE_ID;
740 l2info->cookie_len += 6;
741 l2info->header_len += 6;
742 break;
743
744 default:
745 l2info->bundle = l2info->cookie[0];
746 break;
747 }
748
749 if (eflag)
750 printf("%s-PIC, cookie-len %u",
751 lp->s,
752 l2info->cookie_len);
753
754 if (l2info->cookie_len > 0) {
755 TCHECK2(p[0],l2info->cookie_len);
756 if (eflag)
757 printf(", cookie 0x");
758 for (idx = 0; idx < l2info->cookie_len; idx++) {
759 l2info->cookie[idx] = p[idx]; /* copy cookie data */
760 if (eflag) printf("%02x",p[idx]);
761 }
762 }
763
764 if (eflag) printf(": "); /* print demarc b/w L2/L3*/
765
766
767 l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len);
768 break;
769 }
770 ++lp;
771 }
772 p+=l2info->cookie_len;
773
774 /* DLT_ specific parsing */
775 switch(l2info->pictype) {
776 case DLT_JUNIPER_MLPPP:
777 switch (l2info->cookie_type) {
778 case LS_COOKIE_ID:
779 l2info->bundle = l2info->cookie[1];
780 break;
781 case AS_COOKIE_ID:
782 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
783 l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
784 break;
785 default:
786 l2info->bundle = l2info->cookie[0];
787 break;
788 }
789 break;
790 case DLT_JUNIPER_MLFR: /* fall through */
791 case DLT_JUNIPER_MFR:
792 switch (l2info->cookie_type) {
793 case LS_COOKIE_ID:
794 l2info->bundle = l2info->cookie[1];
795 break;
796 case AS_COOKIE_ID:
797 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
798 break;
799 default:
800 l2info->bundle = l2info->cookie[0];
801 break;
802 }
803 l2info->proto = EXTRACT_16BITS(p);
804 l2info->header_len += 2;
805 l2info->length -= 2;
806 l2info->caplen -= 2;
807 break;
808 case DLT_JUNIPER_ATM2:
809 TCHECK2(p[0],4);
810 /* ATM cell relay control word present ? */
811 if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK && *p & 0x08) {
812 l2info->header_len += 4;
813 if (eflag)
814 printf("control-word 0x%08x ",EXTRACT_32BITS(p));
815 }
816 break;
817 case DLT_JUNIPER_ATM1:
818 default:
819 break;
820 }
821
822 if (eflag > 1)
823 printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto);
824
825 return 1; /* everything went ok so far. continue parsing */
826 trunc:
827 printf("[|juniper_hdr], length %u",h->len);
828 return 0;
829 }
830
831
832 /*
833 * Local Variables:
834 * c-style: whitesmith
835 * c-basic-offset: 4
836 * End:
837 */