]> The Tcpdump Group git mirrors - tcpdump/blob - print-juniper.c
check for cell-relay controlword between the cookie and the OAM payload
[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.20 2005-06-09 07:56:26 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
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 u_int32_t control_word;
563
564 struct juniper_l2info_t l2info;
565
566 l2info.pictype = DLT_JUNIPER_ATM2;
567 if(juniper_parse_header(p, h, &l2info) == 0)
568 return l2info.header_len;
569
570 p+=l2info.header_len;
571
572 if (l2info.cookie[7] & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
573 control_word = EXTRACT_32BITS(p);
574 if(control_word == 0 || control_word == 0x08000000) {
575 l2info.header_len += 4;
576 l2info.length -= 4;
577 p += 4;
578 }
579 oam_print(p,l2info.length);
580 return l2info.header_len;
581 }
582
583 if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
584 EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
585
586 if (llc_print(p, l2info.length, l2info.caplen, NULL, NULL,
587 &extracted_ethertype) != 0)
588 return l2info.header_len;
589 }
590
591 if (l2info.direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
592 (EXTRACT_32BITS(l2info.cookie) & ATM2_GAP_COUNT_MASK)) {
593 ether_print(p, l2info.length, l2info.caplen);
594 return l2info.header_len;
595 }
596
597 if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
598 isoclns_print(p + 1, l2info.length - 1, l2info.caplen - 1);
599 /* FIXME check if frame was recognized */
600 return l2info.header_len;
601 }
602
603 if(juniper_ppp_heuristic_guess(p, l2info.length) != 0) /* PPPoA vcmux encaps ? */
604 return l2info.header_len;
605
606 if(ip_heuristic_guess(p, l2info.length) != 0) /* last try - vcmux encaps ? */
607 return l2info.header_len;
608
609 return l2info.header_len;
610 }
611 #endif
612
613
614 /* try to guess, based on all PPP protos that are supported in
615 * a juniper router if the payload data is encapsulated using PPP */
616 int
617 juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
618
619 switch(EXTRACT_16BITS(p)) {
620 case PPP_IP :
621 case PPP_OSI :
622 case PPP_MPLS_UCAST :
623 case PPP_MPLS_MCAST :
624 case PPP_IPCP :
625 case PPP_OSICP :
626 case PPP_MPLSCP :
627 case PPP_LCP :
628 case PPP_PAP :
629 case PPP_CHAP :
630 case PPP_ML :
631 #ifdef INET6
632 case PPP_IPV6 :
633 case PPP_IPV6CP :
634 #endif
635 ppp_print(p, length);
636 break;
637
638 default:
639 return 0; /* did not find a ppp header */
640 break;
641 }
642 return 1; /* we printed a ppp packet */
643 }
644
645 int
646 ip_heuristic_guess(register const u_char *p, u_int length) {
647
648 switch(p[0]) {
649 case 0x45:
650 case 0x46:
651 case 0x47:
652 case 0x48:
653 case 0x49:
654 case 0x4a:
655 case 0x4b:
656 case 0x4c:
657 case 0x4d:
658 case 0x4e:
659 case 0x4f:
660 ip_print(gndo, p, length);
661 break;
662 #ifdef INET6
663 case 0x60:
664 case 0x61:
665 case 0x62:
666 case 0x63:
667 case 0x64:
668 case 0x65:
669 case 0x66:
670 case 0x67:
671 case 0x68:
672 case 0x69:
673 case 0x6a:
674 case 0x6b:
675 case 0x6c:
676 case 0x6d:
677 case 0x6e:
678 case 0x6f:
679 ip6_print(p, length);
680 break;
681 #endif
682 default:
683 return 0; /* did not find a ip header */
684 break;
685 }
686 return 1; /* we printed an v4/v6 packet */
687 }
688
689 static int
690 juniper_parse_header (const u_char *p, const struct pcap_pkthdr *h, struct juniper_l2info_t *l2info) {
691
692 struct juniper_cookie_table_t *lp = juniper_cookie_table;
693 u_int idx;
694
695 l2info->header_len = 0;
696 l2info->cookie_len = 0;
697 l2info->proto = 0;
698
699
700 l2info->length = h->len;
701 l2info->caplen = h->caplen;
702 l2info->direction = p[3]&JUNIPER_BPF_PKT_IN;
703
704 TCHECK2(p[0],4);
705 if (EXTRACT_24BITS(p) != JUNIPER_MGC_NUMBER) /* magic number found ? */
706 return 0;
707 else
708 l2info->header_len = 4;
709
710 if (eflag) /* print direction */
711 printf("%3s ",tok2str(juniper_direction_values,"---",l2info->direction));
712
713 if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
714 if (eflag)
715 printf("no-L2-hdr, ");
716
717 /* there is no link-layer present -
718 * perform the v4/v6 heuristics
719 * to figure out what it is
720 */
721 TCHECK2(p[8],1);
722 if(ip_heuristic_guess(p+8,l2info->length-8) == 0)
723 printf("no IP-hdr found!");
724
725 l2info->header_len+=4;
726 return 0; /* stop parsing the output further */
727
728 }
729
730 p+=l2info->header_len;
731 l2info->length -= l2info->header_len;
732 l2info->caplen -= l2info->header_len;
733
734 /* search through the cookie table and copy values matching for our PIC type */
735 while (lp->s != NULL) {
736 if (lp->pictype == l2info->pictype) {
737
738 l2info->cookie_len = lp->cookie_len;
739 l2info->header_len += lp->cookie_len;
740
741 switch (p[0]) {
742 case LS_COOKIE_ID:
743 l2info->cookie_type = LS_COOKIE_ID;
744 l2info->cookie_len += 2;
745 l2info->header_len += 2;
746 break;
747 case AS_COOKIE_ID:
748 l2info->cookie_type = AS_COOKIE_ID;
749 l2info->cookie_len += 6;
750 l2info->header_len += 6;
751 break;
752
753 default:
754 l2info->bundle = l2info->cookie[0];
755 break;
756 }
757
758 if (eflag)
759 printf("%s-PIC, cookie-len %u",
760 lp->s,
761 l2info->cookie_len);
762
763 if (l2info->cookie_len > 0) {
764 TCHECK2(p[0],l2info->cookie_len);
765 if (eflag)
766 printf(", cookie 0x");
767 for (idx = 0; idx < l2info->cookie_len; idx++) {
768 l2info->cookie[idx] = p[idx]; /* copy cookie data */
769 if (eflag) printf("%02x",p[idx]);
770 }
771 }
772
773 if (eflag) printf(": "); /* print demarc b/w L2/L3*/
774
775
776 l2info->proto = EXTRACT_16BITS(p+l2info->cookie_len);
777 break;
778 }
779 ++lp;
780 }
781 p+=l2info->cookie_len;
782
783 /* DLT_ specific parsing */
784 switch(l2info->pictype) {
785 case DLT_JUNIPER_MLPPP:
786 switch (l2info->cookie_type) {
787 case LS_COOKIE_ID:
788 l2info->bundle = l2info->cookie[1];
789 break;
790 case AS_COOKIE_ID:
791 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
792 l2info->proto = (l2info->cookie[5])&JUNIPER_LSQ_L3_PROTO_MASK;
793 break;
794 default:
795 l2info->bundle = l2info->cookie[0];
796 break;
797 }
798 break;
799 case DLT_JUNIPER_MLFR: /* fall through */
800 case DLT_JUNIPER_MFR:
801 switch (l2info->cookie_type) {
802 case LS_COOKIE_ID:
803 l2info->bundle = l2info->cookie[1];
804 break;
805 case AS_COOKIE_ID:
806 l2info->bundle = (EXTRACT_16BITS(&l2info->cookie[6])>>3)&0xfff;
807 break;
808 default:
809 l2info->bundle = l2info->cookie[0];
810 break;
811 }
812 l2info->proto = EXTRACT_16BITS(p);
813 l2info->header_len += 2;
814 l2info->length -= 2;
815 l2info->caplen -= 2;
816 break;
817 case DLT_JUNIPER_ATM2:
818 TCHECK2(p[0],4);
819 /* ATM cell relay control word present ? */
820 if (l2info->cookie[7] & ATM2_PKT_TYPE_MASK && *p & 0x08) {
821 l2info->header_len += 4;
822 if (eflag)
823 printf("control-word 0x%08x ",EXTRACT_32BITS(p));
824 }
825 break;
826 case DLT_JUNIPER_ATM1:
827 default:
828 break;
829 }
830
831 if (eflag > 1)
832 printf("hlen %u, proto 0x%04x, ",l2info->header_len,l2info->proto);
833
834 return 1; /* everything went ok so far. continue parsing */
835 trunc:
836 printf("[|juniper_hdr], length %u",h->len);
837 return 0;
838 }
839
840
841 /*
842 * Local Variables:
843 * c-style: whitesmith
844 * c-basic-offset: 4
845 * End:
846 */