]> The Tcpdump Group git mirrors - tcpdump/blob - print-juniper.c
From Albert Chin: don't call "ip6_print()" if it's not available.
[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.19 2005-06-07 21:53:50 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 #ifdef INET6
407 case JUNIPER_LSQ_L3_PROTO_IPV6:
408 ip6_print(p,l2info.length);
409 return l2info.header_len;
410 #endif
411 case JUNIPER_LSQ_L3_PROTO_MPLS:
412 mpls_print(p,l2info.length);
413 return l2info.header_len;
414 case JUNIPER_LSQ_L3_PROTO_ISO:
415 isoclns_print(p,l2info.length,l2info.caplen);
416 return l2info.header_len;
417 default:
418 break;
419 }
420
421 /* zero length cookie ? */
422 switch (EXTRACT_16BITS(&l2info.cookie)) {
423 case PPP_OSI:
424 ppp_print(p-2,l2info.length+2);
425 break;
426 case (PPP_ADDRESS << 8 | PPP_CONTROL): /* fall through */
427 default:
428 ppp_print(p,l2info.length);
429 break;
430 }
431
432 return l2info.header_len;
433 }
434 #endif
435
436
437 #ifdef DLT_JUNIPER_MFR
438 u_int
439 juniper_mfr_print(const struct pcap_pkthdr *h, register const u_char *p)
440 {
441 struct juniper_l2info_t l2info;
442
443 l2info.pictype = DLT_JUNIPER_MFR;
444 if(juniper_parse_header(p, h, &l2info) == 0)
445 return l2info.header_len;
446
447 p+=l2info.header_len;
448 /* suppress Bundle-ID if frame was captured on a child-link */
449 if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
450 switch (l2info.proto) {
451 case (LLCSAP_ISONS<<8 | LLCSAP_ISONS):
452 isoclns_print(p+1, l2info.length-1, l2info.caplen-1);
453 break;
454 case (LLC_UI<<8 | NLPID_Q933):
455 case (LLC_UI<<8 | NLPID_IP):
456 case (LLC_UI<<8 | NLPID_IP6):
457 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
458 isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
459 break;
460 default:
461 printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
462 }
463
464 return l2info.header_len;
465 }
466 #endif
467
468 #ifdef DLT_JUNIPER_MLFR
469 u_int
470 juniper_mlfr_print(const struct pcap_pkthdr *h, register const u_char *p)
471 {
472 struct juniper_l2info_t l2info;
473
474 l2info.pictype = DLT_JUNIPER_MLFR;
475 if(juniper_parse_header(p, h, &l2info) == 0)
476 return l2info.header_len;
477
478 p+=l2info.header_len;
479
480 /* suppress Bundle-ID if frame was captured on a child-link */
481 if (eflag && EXTRACT_32BITS(l2info.cookie) != 1) printf("Bundle-ID %u, ",l2info.bundle);
482 switch (l2info.proto) {
483 case (LLC_UI):
484 case (LLC_UI<<8):
485 isoclns_print(p, l2info.length, l2info.caplen);
486 break;
487 case (LLC_UI<<8 | NLPID_Q933):
488 case (LLC_UI<<8 | NLPID_IP):
489 case (LLC_UI<<8 | NLPID_IP6):
490 /* pass IP{4,6} to the OSI layer for proper link-layer printing */
491 isoclns_print(p-1, l2info.length+1, l2info.caplen+1);
492 break;
493 default:
494 printf("unknown protocol 0x%04x, length %u",l2info.proto, l2info.length);
495 }
496
497 return l2info.header_len;
498 }
499 #endif
500
501 /*
502 * ATM1 PIC cookie format
503 *
504 * +-----+-------------------------+-------------------------------+
505 * |fmtid| vc index | channel ID |
506 * +-----+-------------------------+-------------------------------+
507 */
508
509 #ifdef DLT_JUNIPER_ATM1
510 u_int
511 juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p)
512 {
513 u_int16_t extracted_ethertype;
514
515 struct juniper_l2info_t l2info;
516
517 l2info.pictype = DLT_JUNIPER_ATM1;
518 if(juniper_parse_header(p, h, &l2info) == 0)
519 return l2info.header_len;
520
521 p+=l2info.header_len;
522
523 if (l2info.cookie[0] == 0x80) { /* OAM cell ? */
524 oam_print(p,l2info.length);
525 return l2info.header_len;
526 }
527
528 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
529 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
530
531 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
532 &extracted_ethertype) != 0)
533 return l2info.header_len;
534 }
535
536 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
537 isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
538 /* FIXME check if frame was recognized */
539 return l2info.header_len;
540 }
541
542 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
543 return l2info.header_len;
544
545 return l2info.header_len;
546 }
547 #endif
548
549 /*
550 * ATM2 PIC cookie format
551 *
552 * +-------------------------------+---------+---+-----+-----------+
553 * | channel ID | reserv |AAL| CCRQ| gap cnt |
554 * +-------------------------------+---------+---+-----+-----------+
555 */
556
557 #ifdef DLT_JUNIPER_ATM2
558 u_int
559 juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p)
560 {
561 u_int16_t extracted_ethertype;
562
563 struct juniper_l2info_t l2info;
564
565 l2info.pictype = DLT_JUNIPER_ATM2;
566 if(juniper_parse_header(p, h, &l2info) == 0)
567 return l2info.header_len;
568
569 p+=l2info.header_len;
570
571 if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
572 oam_print(p,l2info.length);
573 return l2info.header_len;
574 }
575
576 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
577 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
578
579 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
580 &extracted_ethertype) != 0)
581 return l2info.header_len;
582 }
583
584 if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
585 (EXTRACT_32BITS(l2info.cookie) & ATM2_GAP_COUNT_MASK)) {
586 ether_print(p, l2info.length, l2info.caplen);
587 return l2info.header_len;
588 }
589
590 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
591 isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
592 /* FIXME check if frame was recognized */
593 return l2info.header_len;
594 }
595
596 if(juniper_ppp_heuristic_guess(p, l2info.length) != 0) /* PPPoA vcmux encaps ? */
597 return l2info.header_len;
598
599 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
600 return l2info.header_len;
601
602 return l2info.header_len;
603 }
604 #endif
605
606
607 /* try to guess, based on all PPP protos that are supported in
608 * a juniper router if the payload data is encapsulated using PPP */
609 int
610 juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
611
612 switch(EXTRACT_16BITS(p)) {
613 case PPP_IP :
614 case PPP_OSI :
615 case PPP_MPLS_UCAST :
616 case PPP_MPLS_MCAST :
617 case PPP_IPCP :
618 case PPP_OSICP :
619 case PPP_MPLSCP :
620 case PPP_LCP :
621 case PPP_PAP :
622 case PPP_CHAP :
623 case PPP_ML :
624 #ifdef INET6
625 case PPP_IPV6 :
626 case PPP_IPV6CP :
627 #endif
628 ppp_print(p, length);
629 break;
630
631 default:
632 return 0; /* did not find a ppp header */
633 break;
634 }
635 return 1; /* we printed a ppp packet */
636 }
637
638 int
639 ip_heuristic_guess(register const u_char *p, u_int length) {
640
641 switch(p[0]) {
642 case 0x45:
643 case 0x46:
644 case 0x47:
645 case 0x48:
646 case 0x49:
647 case 0x4a:
648 case 0x4b:
649 case 0x4c:
650 case 0x4d:
651 case 0x4e:
652 case 0x4f:
653 ip_print(gndo, p, length);
654 break;
655 #ifdef INET6
656 case 0x60:
657 case 0x61:
658 case 0x62:
659 case 0x63:
660 case 0x64:
661 case 0x65:
662 case 0x66:
663 case 0x67:
664 case 0x68:
665 case 0x69:
666 case 0x6a:
667 case 0x6b:
668 case 0x6c:
669 case 0x6d:
670 case 0x6e:
671 case 0x6f:
672 ip6_print(p, length);
673 break;
674 #endif
675 default:
676 return 0; /* did not find a ip header */
677 break;
678 }
679 return 1; /* we printed an v4/v6 packet */
680 }
681
682 static int
683 juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) {
684
685 struct juniper_cookie_table_t *lp = juniper_cookie_table;
686 u_int idx;
687
688 l2info->header_len = 0;
689 l2info->cookie_len = 0;
690 l2info->proto = 0;
691
692
693 l2info->length = h->len;
694 l2info->caplen = h->caplen;
695 l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
696
697 TCHECK2(p[0],4);
698 if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) /* magic number found ? */
699 return 0;
700 else
701 l2info->header_len = 4;
702
703 if (eflag) /* print direction */
704 printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction));
705
706 if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
707 if (eflag)
708 printf("no-L2-hdr, ");
709
710 /* there is no link-layer present -
711 * perform the v4/v6 heuristics
712 * to figure out what it is
713 */
714 TCHECK2(p[8],1);
715 if(ip_heuristic_guess(p+8,l2info->length-8) == 0)
716 printf("no IP-hdr found!");
717
718 l2info->header_len+=4;
719 return 0; /* stop parsing the output further */
720
721 }
722
723 p+=l2info->header_len;
724 l2info->length -= l2info->header_len;
725 l2info->caplen -= l2info->header_len;
726
727 /* search through the cookie table and copy values matching for our PIC type */
728 while (lp->s != NULL) {
729 if (lp->pictype == l2info->pictype) {
730
731 l2info->cookie_len = lp->cookie_len;
732 l2info->header_len += lp->cookie_len;
733
734 switch (p[0]) {
735 case LS_COOKIE_ID:
736 l2info->cookie_type = LS_COOKIE_ID;
737 l2info->cookie_len += 2;
738 l2info->header_len += 2;
739 break;
740 case AS_COOKIE_ID:
741 l2info->cookie_type = AS_COOKIE_ID;
742 l2info->cookie_len += 6;
743 l2info->header_len += 6;
744 break;
745
746 default:
747 l2info->bundle = l2info->cookie[0];
748 break;
749 }
750
751 if (eflag)
752 printf("%s-PIC, cookie-len %u",
753 lp->s,
754 l2info->cookie_len);
755
756 if (l2info->cookie_len > 0) {
757 TCHECK2(p[0],l2info->cookie_len);
758 if (eflag)
759 printf(", cookie 0x");
760 for (idx = 0; idx < l2info->cookie_len; idx++) {
761 l2info->cookie[idx] = p[idx]; /* copy cookie data */
762 if (eflag) printf("%02x",p[idx]);
763 }
764 }
765
766 if (eflag) printf(": "); /* print demarc b/w L2/L3*/
767
768
769 l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len);
770 break;
771 }
772 ++lp;
773 }
774 p+=l2info->cookie_len;
775
776 /* DLT_ specific parsing */
777 switch(l2info->pictype) {
778 case DLT_JUNIPER_MLPPP:
779 switch (l2info->cookie_type) {
780 case LS_COOKIE_ID:
781 l2info->bundle = l2info->cookie[1];
782 break;
783 case AS_COOKIE_ID:
784 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
785 l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
786 break;
787 default:
788 l2info->bundle = l2info->cookie[0];
789 break;
790 }
791 break;
792 case DLT_JUNIPER_MLFR: /* fall through */
793 case DLT_JUNIPER_MFR:
794 switch (l2info->cookie_type) {
795 case LS_COOKIE_ID:
796 l2info->bundle = l2info->cookie[1];
797 break;
798 case AS_COOKIE_ID:
799 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
800 break;
801 default:
802 l2info->bundle = l2info->cookie[0];
803 break;
804 }
805 l2info->proto = EXTRACT_16BITS(p);
806 l2info->header_len += 2;
807 l2info->length -= 2;
808 l2info->caplen -= 2;
809 break;
810 case DLT_JUNIPER_ATM2:
811 TCHECK2(p[0],4);
812 /* ATM cell relay control word present ? */
813 if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK && *p & 0x08) {
814 l2info->header_len += 4;
815 if (eflag)
816 printf("control-word 0x%08x ",EXTRACT_32BITS(p));
817 }
818 break;
819 case DLT_JUNIPER_ATM1:
820 default:
821 break;
822 }
823
824 if (eflag > 1)
825 printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto);
826
827 return 1; /* everything went ok so far. continue parsing */
828 trunc:
829 printf("[|juniper_hdr], length %u",h->len);
830 return 0;
831 }
832
833
834 /*
835 * Local Variables:
836 * c-style: whitesmith
837 * c-basic-offset: 4
838 * End:
839 */