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