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